Invalid Cast Exception while using LINQ
I'm a classic newbie...
i can compile my program, but get an invalidca开发者_如何学JAVAst excpetion when running the programm
what's wrong with my code. i don't not what to seach for :(
This is my code (.net 3.5)
class Element{
private int i;
public int I { get { return i; } set { i = value; } }
private string s;
public string S { get { return s; } set { s = value; } }
public Element(string _s, int _i) {
this.s = _s;
this.i = _i;
}
}
class myDict : Dictionary<string, Element> {
public void afunction() {
}
}
class Program {
static void Main(string[] args) {
myDict myDict = new myDict();
myDict.Add("a", new Element("x", 23));
myDict.Add("b", new Element("y", 48));
var sortedDict = ((from entry in myDict orderby entry.Key descending select entry).Take(10));
myDict = (myDict)sortedDict.ToDictionary(v => v.Key, v => v.Value);
foreach (KeyValuePair<string, Element> kvp in myDict) {
System.Console.WriteLine("-> " +kvp.Key + " " + kvp.Value);
}
Console.ReadLine();
}
}
thanks! michael :)
Hello
Hi there.
I'm a classic newbie.
Welcome aboard.
I can compile my program, but get an invalid cast exception when running the program
A cast operator often means "I am telling the compiler that this conversion is valid. If I make a mistake, throw an invalid cast exception at runtime."
what's wrong with my code. I don't know what to seach for.
Well then, rather than handing you a fish -- the cast on the dictionary is invalid -- let's teach you how to catch your own fish.
Compile your program in debug mode and run it in the debugger. The debugger should break at the exact site of the exception. You can then analyze what is wrong at that exact site.
If for some reason you cannot run your code in the debugger, compile your program in debug mode and run it normally. When you get an exception, look at the "stack trace" part of the exception. It should have the line number of the site of the exception, so that you can then examine that code.
And if for some reason you cannot do that, use the exception message to try and figure it out. An "invalid cast exception" implies that the bad behaviour is the result of a cast operator. There are two places in your program where a cast operator is used. There's an explicit use in the cast on the dictionary, and there's an implicit use in the foreach loop.
Many people are surprised to learn about the latter. When you say
foreach(Giraffe giraffe in animals)
that actually means "cast every animal in the list of animals to Giraffe, and give an invalid cast exception if one of them is a Tiger or a Wallaby or something". It does not mean "ignore all the animals that are not giraffes" -- if you want that, then say
foreach(Giraffe giraffe in animals.OfType<Giraffe>())
The problem will almost certainly be in one of those two places.
I think the issue is that you're casting the result of sortedDict.ToDictionary() as a myDict.
myDict = (myDict)sortedDict.ToDictionary(v => v.Key, v => v.Value);
You cannot do this:
myDict = (myDict)sortedDict.ToDictionary(v => v.Key, v => v.Value);
When you call ToDictionary, you create a Dictionary<string, Element>
, not a myDict
instance. That cast is not valid.
However, there's no reason (in this case) to do so. You can just use the sortedDict
results directly.
If you want to do this, I'd recommend adding a constructor to myDict
that takes an IEnumerable<KeyValuePair<string,Element>>
. You could then do:
class myDict : Dictionary<string, Element> {
public myDict() {}
public myDict(IEnumerable<KeyValuePair<string, Element>> pairs)
{
foreach(var pair in pairs)
this.Add(pair.Key, pair.Value); // Add in all elements
}
}
Then, instead of the cast, you can do:
myDict myDict = new myDict();
myDict.Add("a", new Element("x", 23));
myDict.Add("b", new Element("y", 48));
var sortedDict = ((from entry in myDict orderby entry.Key descending select entry).Take(10));
myDict = new myDict(sortedDict);
That being said, it's a bad idea to subclass Dictionary<TKey,TValue>
directly. If you want to make a custom dictionary, you should encapsulate the framework dictionary in your own class, and implement IDictionary<TKey,TValue>
instead.
The ToDictionary call returns a Dictionary<string, Element>
. Just because myDict is a Dictionary<string, Element>
doesn't mean that a Dictionary<string, Element>
is a myDict.
ToDictionary()
does not return a myDict
class, it returns a Dictionary
class. You cannot cast from Dictionary
to myDict
, although because myDict
derives from Dictionary
, you can cast the other way.
Your problem is that you cannot cast back to myDict as it is a much more specific class than Dictionary
精彩评论