|
Thanks for the information paul.
|
|
|
|
|
pmarfleet wrote: I believe that in VS2008, it will be possible to build your code against a specific version of the framework.
Your right but it's limited to 2.0, 3.0 and 3.5, you wont be able to do 1.0 or 1.1.
|
|
|
|
|
You can compile for .NET 1.0 and 1.1 in both VS2005 and VS2008, you just have to write the appropriate MSBuild targets (or download them, e.g. from here[^]).
|
|
|
|
|
I need to represent some data in memory which needs the performance of a
Dictionary lookup, but the key for these data consists of multible values,
e.g.:
Data has a structure like this:
ProductId (key) InventId (key) Property1 (value) Property2 (value)
1234 1 [somevalue] [somevalue]
1234 2 [somevalue] [somevalue]
1237 1 [somevalue] [somevalue]
The unique key in this case is a combination of 'ProductId' and 'InventId'
My first idea was to startout having the key a new Generic class e.g.
Key<T1,T2> for use with Dictionary<Key<T1,T2>, ProductRelation> etc..
- But this solution is not usable for more than two values for the key ....
What is the "best" Practice for this scenario? - if you want max flexibility and max
performance ??
Regards, Rune
|
|
|
|
|
Hello,
Why not use a non generic class or struct?
All the best,
Martin
|
|
|
|
|
a nongeneric collection would be a lot slower.
I could use a object[] as the key, but that would give a heavy performance penalty when boxing/unboxing values ... that's why generics is so good in this case.
|
|
|
|
|
Create a wrapper object that overrides the GetHashCode method.
Actually, when it is numeric I just make my hash use a string as the first key and look up "id_id"
The other option is to have a hash containing a hash. It would require two look ups but work reasonably well.
Dictionary<productid, dictionary<inventoryid,="" myobject="">>;
Need a C# Consultant? I'm available.
Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
|
|
|
|
|
Sounds like the way to go ...
This performs quite well, but it still does not solve having n-number of values as a key, only two this time ...
<br />
void Main()<br />
{<br />
Dictionary<Key<int, string>, MyClass> dictionary = new Dictionary<Key<int, string>, MyClass>();<br />
<br />
MyClass obj = new MyClass();<br />
dictionary.Add(obj.GetKey(), obj);<br />
}<br />
<br />
<br />
<br />
<br />
public struct Key<T1, T2> : IEquatable<Key<T1, T2>><br />
{<br />
public Key(T1 keyValue1, T2 keyValue2)<br />
{<br />
_keyValue1 = keyValue1;<br />
_keyValue2 = keyValue2;<br />
}<br />
<br />
private T1 _keyValue1;<br />
private T2 _keyValue2;<br />
<br />
public override int GetHashCode()<br />
{<br />
return _keyValue1.GetHashCode() ^ _keyValue2.GetHashCode();<br />
}<br />
<br />
public override bool Equals(object other)<br />
{<br />
return this.GetHashCode().Equals(other.GetHashCode());<br />
}<br />
<br />
}<br />
<br />
<br />
<br />
public sealed class MyClass<br />
{<br />
<br />
private int _Key1;<br />
private string _Key2;<br />
private string _Value1;<br />
<br />
public int Key1<br />
{<br />
get { return _Key1; }<br />
set { _Key1 = value; }<br />
}<br />
<br />
public string Key2<br />
{<br />
get { return _Key2; }<br />
set { _Key2 = value; }<br />
}<br />
<br />
public string Value1<br />
{<br />
get { return _Value1; }<br />
set { _Value1 = value; }<br />
}<br />
<br />
public Key<int, string> GetKey()<br />
{<br />
return new Key<int, string>(this.Key1, this.Key2);<br />
}<br />
<br />
}<br />
<br />
|
|
|
|
|
How about a Dictionary of Dictionaries?
I don't know how variable you can get though.
Gives me something to think about tonight...
|
|
|
|
|
Under the right circumstances it would probably perform very well, but for more than two values you are screwed...
|
|
|
|
|
|
I like a good programming exercise. What I've been concentrating on is the "max flexibility" part, but with a lack of type safety I don't see how both can be achieved.
This is just a little test program that uses the class I'm working on.
namespace Test
{
class Test
{
[System.STAThreadAttribute]
static void
Main
(
string[] args
)
{
PIEBALD.Types.Hierarchary store = new PIEBALD.Types.Hierarchary
(
typeof(int)
,
typeof(int)
,
typeof(string)
) ;
store [ 1234 , 1 , "Property1" ] = "1234 1 1" ;
store [ 1234 , 1 , "Property2" ] = "1234 1 2" ;
store [ 1234 , 2 , "Property1" ] = "1234 2 1" ;
store [ 1234 , 2 , "Property2" ] = "1234 2 2" ;
store [ 1237 , 1 , "Property1" ] = "1237 1 1" ;
store [ 1237 , 1 , "Property2" ] = "1237 1 2" ;
System.Console.WriteLine
( "ProductId (key) InventId (key) Property1 (value) Property2 (value)" ) ;
foreach ( object k1 in store.Keys() )
{
foreach ( object k2 in store.Keys ( k1 ) )
{
System.Console.WriteLine
(
"{0,-17} {1,-16} {2,-20} {3,-20}"
,
k1
,
k2
,
store [ k1 , k2 , "Property1" ]
,
store [ k1 , k2 , "Property2" ]
) ;
}
}
return ;
}
}
}
|
|
|
|
|
Clever, but you don't avoid the unfortunate cast to and from object without the use of generics...
I've been working on a generic KeyedList, a kind of "brother" to the KeyedCollection, but for use with multible keys.
It's used like this
<code>
KeyedList<string, int, MyObject> keyedlist = new KeyedList<string, int, MyObject>();
keyedlist.Add(new MyObject("kvalue1",123, "actual content"));
keyedlist.Add(new MyObject("kvalue2",123, "actual content"));
// etc...
string key1 = "kvalue1";
int key2 = 123;
if(keyedlist.Contains(key1, key2);
{
MyObject obj = keyedlist[key1, key2];
// etc..
}
</code>
but I had make a new class for each number of keytypes for a coollection...
For 1, 2 and 3 keys the outcome was:
<code>
class KeyedList<TKey1, TObject>
{
}
class KeyedList<TKey1, TKey2, TObject>
{
}
class KeyedList<TKey1, TKey2, TKey3, TObject>
{
}
// etc...
</code>
I was hoping to avoid that ...
My dreams was that you could declare n-number of TKey types in a generic class....
Something like this:
<code>
class KeyedList<TKey[], TObject>
{
void Somemethod()
{
foreach(TKey keytype in TKey[])
{
// etc...
}
}
}
// so you could use it like this
KeyedList<int, int, Guid, MyObject> list = new ...
// or
KeyedList<string, MyObject> list = new ...
// with out having to make new class declare for each ....
</code>
Maybe in the next C# version...
|
|
|
|
|
I don't think the key types matter as much as the value type, generally they go in but don't come out.
Because I was aiming for max flexibility I didn't provide the ability to specify the value type, but it could be done.
|
|
|
|
|
I added the ability to specify the value type and the key type when desired.
namespace Test
{
class Test
{
[System.STAThreadAttribute]
static void
Main
(
string[] args
)
{
try
{
PIEBALD.Types.Hierarchary<string> store =
new PIEBALD.Types.Hierarchary<string>
(
typeof(int)
,
typeof(int)
,
typeof(string)
) ;
store [ 1234 , 1 , "Property1" ] = "1234 1 1" ;
store [ 1234 , 1 , "Property2" ] = "1234 1 2" ;
store [ 1234 , 2 , "Property1" ] = "1234 2 1" ;
store [ 1234 , 2 , "Property2" ] = "1234 2 2" ;
store [ 1237 , 1 , "Property1" ] = "1237 1 1" ;
store [ 1237 , 1 , "Property2" ] = "1237 1 2" ;
System.Console.WriteLine ( "ProductId (key) InventId (key) Property1 (value) Property2 (value)" ) ;
foreach ( int k1 in store.Keys<int>() )
{
foreach ( int k2 in store.Keys<int> ( k1 ) )
{
System.Console.WriteLine
(
"{0,-17} {1,-16} {2,-20} {3,-20}"
,
k1
,
k2
,
store [ k1 , k2 , "Property1" ]
,
store [ k1 , k2 , "Property2" ]
) ;
}
}
}
catch ( System.Exception err )
{
System.Console.WriteLine ( err.Message ) ;
}
return ;
}
}
}
|
|
|
|
|
I have a method which is passed an Exception.
I'd like to find out which Exception it is (ie, was it ArgumentNullException, was it a COM Exception, etc).
How do I address this? I don't have control of the original Try/Catch statement in this method, it just receives an Exception which is passed, not thrown.
|
|
|
|
|
if(ex is ArgumentNullException)
{
MessageBox.Show("Thau shall not nullify");
}
fafafa, ringakta icke sådant som bringa ack så naggande högönsklig välmåga å baronens ära.
|
|
|
|
|
Thanks, that was exactly what I was looking for - what comparator to use. I was trying "==" and getting nowhere. Sounds like "is" is the way to go.
I was also just casting from the general exception to the specific exception and seeing what happened. I was not getting much info there .
|
|
|
|
|
How can I access the specific fields and properties?
public string GetErrorCode(Exception ex)<br />
{<br />
if (ex is COMException)<br />
{<br />
return ex.ErrorCode.ToString();<br />
}<br />
else<br />
{<br />
return "";<br />
}<br />
}
This doesn't work, the compiler complains that System.Exception doesn't contain a definition for ErrorCode.
I tried casting ex using
ex = (COMException)ex
but it fails the same way.
|
|
|
|
|
Hello,
You have to cast it to the Type!
if (ex is COMException)
{
COMException comEx = ex as COMException
return comEx.ErrorCode.ToString();
}
or
COMException comEx = ex as COMException
if(comEx !=null)
{
return comEx.ErrorCode.ToString();
}
All the best,
Martin
|
|
|
|
|
Interesting, I used a direct cast (as in my example posted further down) instead of "as", and it appears to work fine. Any caveats there I should know about?
I'm not that familiar with "is" and "as", clearly. Perhaps I should be...
|
|
|
|
|
Hello,
In you example you instanciated a object of COMException bevore casting,
which is not needed at all!
The advantage of using "is" or/and "as" is the check of the complete inheritance tree!
Additionaly you have the possibility (like I showed in the second example) to use "as" without doing the TypeCheck bevor, and not have to have the "fear" of an Exception thrown because of invalid type.
All the best,
Martin
|
|
|
|
|
Right, I would write that first example as:
if (ex is COMException)
{
return ((COMException)ex).ErrorCode.ToString();
}
"Omit needless local variables." -- (To modernize Strunk)
|
|
|
|
|
Got it.
I had to create a new COMException, and cast into that.
COMException COMex = new COMException();<br />
<br />
COMex = (COMException)ex;
then I was fine.
|
|
|
|
|
JoeRip wrote: I had to create a new COMException
No, you didn't. this would have worked just fine:
COMException COMex = (COMException)ex;
The reason it failed initially is that you tried to reuse the ex variable which was already defined as Exception:
ex = (COMException)ex;
You should definately read up on the C# is and as keywords as they are better suited to what you are trying to do.
|
|
|
|
|