1. CS0030 (compiler error) "Cannot convert type "Foo" to "Bar" - This error occurs when trying to explicitly cast one type to a completely unrelated type. This can be reproduced with this code:
class Foo { }
class Bar { }
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
The part that the compiler is complaining about here is specifically the "(Bar)foo" code. There is no conversion, so it complains there.
2. CS0029 (compiler error) "Cannot implicitly convert type 'Foo' to 'Bar'" - This error occurs when trying to implicitly cast one type to a completely unrelated type. This is reproduced with the following code:
class Foo { }
class Bar { }
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
Bar bar = foo;
}
}
This one is similar to the next, however, it doesn't let you know that an explicit conversion exists, and for good reason: there's not one. The compiler here is complaining about the entirety of the second line here, mainly the conflict between the declared type of Bar and the declared type of Foo, as the two have no conversion between them.
3. CS0266 (compiler error) "Cannot implicitly convert type 'double' to 'int' An explicit conversion exists (are you missing a cast?)" - This error will only occur in C# 2.0 and following. It was added in C# 2.0 to add a hint as to whether or not an explicit conversion exists. Think of this one as CS0029 with a tip. It occurs when a casting operation exists for a particular type, but the casting operation must be an explicit cast. This error can be remedied by simply adding an explicit cast. This can be reproduced with the following couple of examples:
class Program
{
static void Main(string[] args)
{
double d = 0;
int i = foo;
}
}
And the other:
class Foo { }
class Bar : Foo { }
class Program
{
static void Main(string[] args)
{
Bar foo = new Foo();
}
}
In both of these situations, a conversion does exist, but you're simply not using it. This is used in situations where an implicit conversion doesn't exist for the type, but an explicit one does. This is a tricky error, though, because in some situations, the cast might cause the compiler to shuttup, only to make the application crash at runtime with the next exception I'll explain.
4. InvalidCastException (runtime error) "Unable to cast object of type 'Foo' to type 'Bar'" - This error occurs when a variable of a parent type is cast to a variable an inherited type, but the constructed type is actually that of the parent, or of a type inherited from the parent that is not within the inheritance tree of the type to which the cast is attempted. This can be reproduced with the following code:
class Foo { }
class Bar : Foo { }
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
The complaint happens not because of the declared type of foo, but because of it's the instantiated type. The instantiated type of Foo is Foo in this example. If I change that first line to the following the error will disappear:
Foo foo = new Bar();The error here goes away, because I've changed the instantiated type of "foo" to Bar, so the conversion is valid, and the runtime marches onward.
For a full reference of all the compiler errors, check out this link.


3 comments:
I'm new to C#, but have a C/C++ background. I'm getting the "error CS0030" when trying to explicitly cast two "unrelated" types which I know to be alike. What got me into this situation is that I have 2+ WebServices which essentially share datatypes between each other. However, because they are imported with a namespace, C# doesn't know that XService.UserContext is the same as YService.UserContext.
I was actually looking for a way to downgrade this error to a warning. Visually inspecting the generated code, I can see that the 2 UserContexts have the same fields in the same order. Now, I suppose it's possible that C# maps these fields nondeterministically, making it dangerous to treat them as the same.
So, basically, what I'm wondering is if there is an elegant solution to this problem. The WebService is still in flux, so I don't think I can really manually edit the Web References.
Unfortunately, no. What you're describing is called "duck typing". "If it walks like a duck, looks like a duck and quacks like a duck, it must be a duck". Right? Wrong.
The two types are completely separate, despite having the same properties.
When adding web references, however, there is a way to use referenced classes whenever necessary. When looking at the "Add service reference" dialog, click the Advanced button. You'll find the option in there.
I want to preface my comment with a disclaimer, because too often, comments on blogs are assumed to be sarcastic retorts. Nothing below should be read with any note of sarcasm. I hope you don't mind my hijacking your blog entry, but like you recently blogged, this could only make it better search engine material. :)
I thought I'd give an update, in case anyone is wrestling with the same problem. I appreciate the help, and was very hopeful about the "Add service reference" dialog. By the way, I realize that, as far as the compiler is concerned, the two types are proverbial apples and oranges. But, C++ allows you to shoot yourself in the foot and treat apples as oranges if you choose. In my case, I actually have some control over the services themselves, so I would have been OK taking that chance.
So, I tried using the Add service reference dialog you mentioned. It took me a while to find because I had been using "Web References" and (as far as I could tell) I needed to create a new project that was a WCF service library to get "service references" or anything with the option you described. I did a little reading up on what WCF meant, and I'm not sure it's compatible with my application. I didn't mention that my web services are on a Tomcat server and that my client/consumer is a mobile device. I got an error when I tried to add the reference to my WCF project from my smart device project, indicating that you couldn't use a desktop project from a smart device project.
It may be a moot point, however, because even though I checked "Reuse types in referenced assemblies", it still namespaced the internal datatypes, so they appear to still be apples and oranges.
For now, I suppose I'll proceed by writing transforms to copy the fields over. If I come up with anything better, I'll let you know.
Post a Comment