If I do:
IList<WSACLI_ComunicazionePersonale> Comunicazioni = (from XmlNode n in m_oNode.SelectNodes("m_Detail_Row")
select new WSACLI_ComunicazionePersonale(n)).ToList();
it works perfect, building my list of WSACLI_ComunicazionePersonale object!
But, if I do:
IList<WSACLI_ComunicazionePersonale> Comunicazioni = m_oNode.SelectNodes("m_Detail_Row").Cast<WSACLI_ComunicazionePersonale>().ToList();
the list is null. Seems that Cast() doesn't call the constructor?
Because casting does not create a new object - it just "re-types"* the existing object so you can use it in a different way. There's no construction involved.
You can treat a Cat as a generic Animal, but it does not create a "new" Cat. Plus, it's still a Cat - you're just interacting with it like it were a generic Animal.
The reverse may also be true - if someone gives you an Animal you could interact with is a such. You could try to interact it as if it were a Cat, but if it is really a Dog, you can't (legally) treat it as a Cat.
* By re-type I mean change the type you're considering the object to be - the underlying type of the object does not change.
You do not create a new object: the instance remains the same. Only the type of the variable that references your instance is modified.
Your second piece of code should read something like this if you want the same functionality as the first:
IList<WSACLI_ComunicazionePersonale> Comunicazioni = m_oNode
.SelectNodes("m_Detail_Row")
.Select(n=> new WSACLI_ComunicazionePersonale(n))
.ToList();
There is no cast because you cannot cast the node to your object. In your first example, you created a new instance and passed the node to the constructor.
Constructor is only invoked when a new instance of Object is created in .Net language, whereas Casting (Type Casting) is a a method of changing the existing type of a object to different Type
Type Casting (On Wikipedia)
In computer science, type conversion, typecasting, and coercion are
different ways of, implicitly or explicitly, changing an entity of one
data type into another. This is done to take advantage of certain
features of type hierarchies or type representations. One example
would be small integers, which can be stored in a compact format and
converted to a larger representation when used in arithmetic
computations. In object-oriented programming, type conversion allows
programs to treat objects of one type as one of their ancestor types
to simplify interacting with them.
Animal animal = new Cat();
Bulldog b = (Bulldog) animal; // if (animal is Bulldog), stat.type(animal) is Bulldog, else an exception
b = animal as Bulldog; // if (animal is Bulldog), b = (Bulldog) animal, else b = null
animal = null;
b = animal as Bulldog; // b == null
Related
If I have an abstract base class called MyBaseClass, and a class deriving from MyBaseClass called MyDerivedClass, is there a way to cast an object that I know is a Dictionary<Guid,MyDerivedClass> to a Dictionary<Guid,MyBaseClass> instead?
I get an invalid cast error when I do:
var dict = (Dictionary<Guid,MyBaseClass>)obj; // Where obj is "object" type but I know is a Dictionary<Guid,MyDerivedClass>.
// This throws an invalid cast error.
The thing that has me confused is that casting an obj that I know is a List<MyDerivedClass> to a List<MyBaseClass> actually works. This works:
var list = (List<MyBaseClass>)obj; // Where obj is "object" type but I know is a List<MyDerivedClass>
// This works
Is there any way to cast an object that is Dictionary<Guid,MyDerivedClass> to Dictionary<Guid,MyBaseClass> without first casting to Dictionary<Guid,MyDerivedClass>? I'd like to avoid have to try casting each derived class if possible.
.NET uses reified generics, so (unlike covariant/contravariant interfaces and arrays) you cannot cast generic classes to have a different signature from what the object actually is. Your example with a List actually doesn't behave the way you say it does:
object obj = new List<MyDerivedClass>();
var list = (List<MyBaseClass>)obj; // invalid cast exception
You can create a new dictionary, though.
var dict = ((Dictionary<Guid, MyDerivedClass>)obj)
.ToDictionary(d => d.Key, d => (MyBaseClass)d.Value);
This will create a copy, and is more expensive than a cast, but for most use cases it won't significantly impact your application's performance.
You could technically create your own class that wraps a differently-typed dictionary and implements an interface like IDictionary<,>, so you could avoid the up-front cost of creating the dictionary but incur slightly more cost as you use the dictionary.
But, in summary, there is no way to simply cast a generic class to a type that it is not.
Why does Console show type B not A, even though a2 was assigned to new B()? I cannot understand exactly what happens in A a2 = new B().
class A { }
class B : A { }
...
A a1 = new A();
A a2 = new B();
Console.WriteLine(a2.GetType());
A variable is just something that points to an object. You can refer an object through a variable of any type that it inherits from (or any interface it implements) but that doesn't change the type of the object itself - this is one of the forms of polymorphism in C#.
Because you have created instance of class B not A and you are able to hold in variable of type A due to inheritance feature of OOP as you are inheriting your B class from A.
But the actual type of the a2 is B not A though it can be represent as A as well, but the GetType() reutrns the run-time type which is B.
You can have a look at this SO post too which explains what the GetType is expected to return for an object and what is typeof() and how we can use is for inheritance hierarchy checking.
Hope it helps.
Just because you refer to it through type A doesn't mean that the actual type suddenly changes to A, it's still a B object. You decided to create one with new B().
You should be aware of the difference between compile time type and runtime type. The compile time type is the type the compiler knows about in this case the type you have declared - A. The runtime type is the type of the object that happens to be referenced by the variable in this case B. Compile time (what the compiler knows about) and runtime (what happens when the program is actually run) is a very important distinction that applies to types, errors and even calculations.
Given an interface IQuestion and an implementation of that interface AMQuestion, suppose the following example:
List<AMQuestion> typed = new List<AMQuestion>();
IList<IQuestion> nonTyped = typed;
This example yields, as expected, a compile error saying the two are not of the same type. But it states an explicit conversion exists. So I change it to look like this:
List<AMQuestion> typed = new List<AMQuestion>();
IList<IQuestion> nonTyped = typed as IList<IQuestion>;
Which then compiles but, at run time, nonTyped is always null. If someone could explain two things:
Why this doesn't work.
How I can achieve the desired effect.
It would be greatly appreciated. Thank you!
The fact that AMQuestion implements the IQuestion interface does not translate into List<AMQuestion> deriving from List<IQuestion>.
Because this cast is illegal, your as operator returns null.
You must cast each item individually as such:
IList<IQuestion> nonTyped = typed.Cast<IQuestion>().ToList();
Regarding your comment, consider the following code, with the usual cliché animal examples:
//Lizard and Donkey inherit from Animal
List<Lizard> lizards = new List<Lizard> { new Lizard() };
List<Donkey> donkeys = new List<Donkey> { new Donkey() };
List<Animal> animals = lizards as List<Animal>; //let's pretend this doesn't return null
animals.Add(new Donkey()); //Reality unravels!
if we were allowed to cast List<Lizard> to a List<Animal>, then we could theoretically add a new Donkey to that list, which would break inheritance.
Why it doesn't work: as returns null if the value's dynamic type cannot be casted to the target type, and List<AMQuestion> cannot be casted to IList<IQuestion>.
But why can't it? Well, check it:
List<AMQuestion> typed = new List<AMQuestion>();
IList<IQuestion> nonTyped = typed as IList<IQuestion>;
nonTyped.Add(new OTQuestion());
AMQuestion whaaaat = typed[0];
IList<IQuestion> says "You can add any IQuestion to me". But that's a promise it couldn't keep if it were a List<AMQuestion>.
Now, if you didn't want to add anything, just view it as a collection of IQuestion-compatible things, then the best thing to do would be to cast it to an IReadOnlyList<IQuestion> with List.AsReadOnly. Since a read-only list can't have strange things added to it, it can be casted properly.
The issue is that List<AMQuestion> cannot be cast to IList<IQuestion>, so using the as operator does not help. Explicit conversion in this case means to cast AMQuestion to IQuestion:
IList<IQuestion> nonTyped = typed.Cast<IQuestion>.ToList();
By the way, you have the term "Covariance" in your title. In IList the type is not covariant. This is exactly why the cast does not exist. The reason is that the IList interface has T in some parameteres and in some return values, so neither in nor out can be used for T. (#Sneftel has a nice example to show why this cast is not allowed.)
If you only need to read from the list, you can use IEnumerable instead:
IEnumerable<IQuestion> = typed;
This will work because IEnumerable<out T> has out defined, since you can't pass it a T as parameter. You should usually make the weakest "promise" possible in your code to keep it extensible.
IList<T> is not covariant for T; it can't be, as the interface defines functions that take values of type T in an "input" position. However, IEnumerable<T> is covariant for T. If you can limit your type to IEnumerable<T>, you can do this:
List<AMQuestion> typed = new List<AMQuestion>();
IEnumerable<IQuestion> nonTyped = typed;
This does not do any conversions on the list.
The reason you cannot convert a List<AMQuestion> to a List<IQuestion> (assuming AMQuestion implements the interface) is that there would have to be several runtime checks on functions like List<T>.Add, to make sure you were really adding an AMQuestion.
The "as" operator will always return null there as no valid cast exists - this is defined behavior. You have to convert or cast the list like this:
IList<IQuestion> nonTyped = typed.Cast<IQuestion>().ToList();
A type with a generic type parameter can only be covariant if this generic type occurs only in read accesses and contravariant, if it occurs only in write accesses. IList<T> allows both, read and write access to values of type T, so it cannot be variant!
Let's assume that you were allowed to assign a List<AMQuestion> to a variable of type IList<IQuestion>. Now let’s implement a class XYQuestion : IQuestion and insert a value of that type into our IList<IQuestion>, which seems perfectly legal. This list still references a List<AMQuestion>, but we cannot insert a XYQuestion into a List<AMQuestion>! Therefore the two list types are not assignment compatible.
IList<IQuestion> list = new List<AMQuestion>(); // Not allowed!
list.Add(new XYQuestion()); // Uuups!
Because List<T> is not a sealed class, it would be possible for a type to exist which would inherit from List<AMQuestion> and implement IList<IQuestion>. Unless you implement such a type yourself, it's extremely unlikely that one will ever actually exist. Nonetheless, it would be perfectly legitimate to say, e.g.
class SillyList : List<AMQuestion>, IList<IQuestion> { ... }
and explicitly implement all the type-specific members of IList<IQuestion>. It would thus also be perfectly legitimate to say "If this variable holds a reference to an instance of a type derived from List<AMQuestion>, and if that instance's type also implements IList<IQuestion>, convert the reference to the latter type.
I need to create a heterogeneous List of objects (custom classes). My first thought was to create a List<ISomeMarkerInterface> but I quickly learned that this is not what I want. My next thought was List<dynamic> and this didn't seem to be a bad idea. However, I was doing some research and came across this article about boxing and unboxing and in the example, they're doing basically what I want using List<Object>.
Aside from the fact that dynamic will be evaluated at runtime and Object at compile-time, what is the difference between List<dynamic> and List<Object>? Aren't they essentially the same thing?
There are 3 "general" types (although not all are real types) in C#: object, var and dynamic.
Object
An actual type, like any other type, with one special rule: if a type doesn't inherit, it inherits from object. From this, it follows that all types inherit from object, directly or indirectly.
Emphasis: object is a type. An object can be of type object, and the type has its methods, like ToString(). Since everything inherits from object, everything can be upcast into object. When you assign an object to an object reference, you are doing upcasting just like when you assign an Elephant type object to an Animal reference where Elephant inherits from Animal.
SomeType x = new SomeType();
object obj = x;
obj.DoSomething();
obj is treated as being of type object at compile time, and will be of type object at runtime (which is logical, since it is an actual type - obj is declared as object so can only be of that type)
obj.DoSomething() will cause a compile-time error, as object does not have this method, regardless of whether SomeType has it.
Var
This is not an actual type, it is merely shorthand for "compiler, figure out the type for me based on the right side of the assignment".
SomeType x = new SomeType();
var obj = x;
obj.DoSomething();
obj is treated as being of type SomeType at compile time, and will be of type SomeType at runtime, just as if you had written "SomeType" instead of "var".
if SomeType has a method DoSomething(), this code will work
if SomeType doesn't have the method, the code will cause a compile-time error
Dynamic
This is a type that tells the compiler to disable compile-time type checking on the variable. An object is treated as having the type dynamic at compile-time and run-time.
SomeType x = new SomeType();
dynamic obj = x;
obj.DoSomething();
obj is of type dynamic at compile and run time
if SomeType has a method DoSomething(), this code will work
if SomeType doesn't have the method, the code will compile, but throw an exception at run-time
note that dynamic can cause exceptions very easily if used carelessly:
public void f(dynamic x)
{
x.DoSomething();
}
This will throw an exception if x is of a type that doesn't have the DoSomething method, but it will still be possible to call it and pass any object as the parameter without a compile-time error, causing an error that only shows itself at run-time, and possibly only in specific circumstances - a potential bug. So if you use dynamic in any kind of public interface of a class, you should always manually type-check at runtime using reflection, carefully deal with exceptions, or not do it in the first place.
Note: the object being referred to never changes its type, of course. While obj may be object, the x that it refers to is still SomeType.
The difference is that if you use object and you try to access some member of your object it will be a compile time error (because object doesn't have this member). In order to work you need to know what the type is and cast it.
With dynamic you can access any member - no compile time error. If the member doesn't exist at runtime it would be a runtime error. This is the way to go if you know that your heretogeneous objects all have the same member for example.
However if this is the case there is another more clear solution: You can define an interface, with this member and then make all your heretogeneous objects implement it and your list can be List<IYourInterface>.
Keep in mind that dynamic's performance might be slightly worse, because of the, well, dynamic type resolution.
Assuming I have the superclass A, and the subclasses A1 and A2 which inherit from A, how could I get the subclass type of the variables in the code below?
A _a1 = new A1();
A _a2 = new A2();
// Need type of A1 and A2 given the variables _a1 and _a2.
Also, if I had another subclass A2_1 which is a sublcass of A2, how do I get the lowest subclass type given code below?
A _a2_1 = new A2_1();
EDIT: Thanks for answers. What a boo boo. Over thinking the problem and didn't even try GetType(). =/
Console.WriteLine(_a1.GetType());
GetType can return the run-time type of the variable irrespective of declaration type.
You could use the GetType() method:
Type type = _a1.GetType();
Type subtype = _a2_1.GetType();
For the first - just use _a1.GetType() and _a2.GetType(). On the 2nd - what do you mean by "lowest subclass type"; or: what answer do you expect... (which might help us understand what you mean...)
GetType() on any object always gives you the real object type, never the type of a superclass. If you are creating instances of subclasses using "new subclass()", then "subclass" is the Type of the object.
Calling GetType() is all you need for your situations.