Cast interface list to implementation list or vice-versa - c#

I am just not getting how to convert or cast List<ISomeImplementation> to List<SomeImplementation>.
// lstOfImplemantation is of type `List<SomeImplementation>`
List<ISomeImplementation> lstOfInterfaces = lstOfImplemantation; // how to convert it.
any help is appreciated.

You can use LINQ in one way:
List<ISomeImplementation> lstOfInterfaces = lstOfImplemantation.Cast<IISomeImplementation>().ToList();
Casting interface to implementation is not good pratice. What if there some other implementations of that interface? You cannot assume that all implemtations are the of type SomeImplementation. If you are sure, use List<SomeImplementation>.

Just because A derives from B, doesn't necessarily mean X<A> derives from X<B>.
In fact, List<T> is invariant in its generic type paramater T. This means List<string> isn't a subtype nor a supertype of List<object>, even though string derives from object.
Imagine if your list of interfaces contained instances of type SomeOtherImplementation. How would the cast work?
Instead, you should create a new list and cast each item in your list of interfaces to the concrete type.
List<SomeImplementation> lstOfImplementation =
lstOfInterfaces.Cast<SomeImplementation>()
.ToList();
If you're not sure whether all instances are of type SomeImplementation, you can filter out those who aren't, using OfType<T>.
List<SomeImplementation> lstOfImplementation =
lstOfInterfaces.OfType<SomeImplementation>()
.ToList();
Read also:
Covariance and Contravariance
Covariance and Contravariance FAQ

Related

Why are generic type definitions in C# not equatable to those they inherit from [duplicate]

For example, if you run the following code...
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
...and you watch IListType variable, you'll find that the whole Type instance has all properties available like FullName and others.
But what happens when you run the code bellow?
Type IListType2 = typeof(List<>).GetInterface("IList`1")
Now IListType got from a generic type definition isn't the same as the first code sample: most Type properties will return null.
The main issue with this is that IListType == IListType2 doesn't equal while they're the same type.
What's going on?
This is ugly...
Now see what happens if you call IListType2.GetGenericTypeDefinition()... It recovers the type information!
It would be great that a .NET Framework development team member could explain us why an already generic type definition which has strangely lost its metadata has IsGenericTypeDefinition property set to false while it's still a generic type definition, and finally, if you call GetGenericTypeDefinition() on it, you recover the type information.
This is strange...
The following equality will be true:
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
// Got interface is "like a generic type definition" since it has
// no type for T generic parameter, and once you call
// GetGenericTypeDefinition() again, it recovers the lost metadata
// and the resulting generic type definition equals the one got from
// List<string>!
Type IListType2 = typeof(List<>).GetInterface("IList`1").GetGenericTypeDefinition();
bool y = IListType == IListType2;
The following types are all different and not connected by an inheritance relationship:
IList<T>
IList<int>
IList<string>
All of these have different Type objects because you can do different things with them. The latter two are the specializations of the former. The first is the generic type definition (which you can obtain through GetGenericTypeDefinition).
There is another part to the explanation. When you say class List<T> : IList<T> then the IList<T> part is not equal to typeof(IList<>) because it is already specialized to T. This is no longer a generic type definition. It is a concrete type such as IList<int>. It is specialized to bind its only type argument to the T that List<T> was specialized to.
Experiment for LINQPad:
Type bound = new List<string>().GetType().GetInterface("IList`1");
bound.GenericTypeArguments.Single().Dump(); //string
Type bound = typeof(List<>).GetInterface("IList`1");
bound.GenericTypeArguments.Single().Dump(); //"T"
(bound.GenericTypeArguments.Single() == typeof(List<>).GetGenericArguments().Single()).Dump(); //true
The first version of IList<T> is the actual typed version of IList<T>, let's say IList<string>.
The second one is the generic definition of IList<T> without a type for T.
That makes the two interfaces different. There are not the same, since the first is a concrete version of the second.

C# -- Knowing a base type of a Generic Type

How can I find out the base type of a generic type?
For example
Func<A, B>
I'd like to be able to say this is a Func<> .. but apparently, Func<,> is different from Func<> -- Is there a way to somehow catch them both, or Func<,,,> etc?
You're looking for GetGenericTypeDefinition:
var t = typeof(Func<int, string>);
var tGeneric = t.GetGenericTypeDefinition();
Assert.AreEqual(typeof(Func<,>), tGeneric);
If you then want to know if a type is one of the many Func<> variants, then your best best is simply to do something like this. Checking type names, as suggested elsewhere is absolutely NOT the way to check type identity:
static Type[] funcGenerics = new[]{
typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>),
/* and so on... */
}
//there are other ways to do the above - but this is the most explicit.
static bool IsFuncType(Type t)
{
if(t.IsGenericTypeDefinition)
return funcGenerics.Any(tt => tt == t);
else if(t.IsGenericType)
return IsFuncType(t.GetGenericTypeDefinition());
return false;
}
Your terminology is incorrect - which I suspect why you got a downvote on your question. A base type is one that a type inherits from (not an interface, which is different, although conceptually very similar).
A generic type definition is best thought of as being like a template (the strong qualification there because the term 'template' is used in C++ and, while visually similar they are very different in implementation).
More accurately, Func<,> is a generic type definition whereas Func<int, string> is a closed generic (the 'generic type').
You can also have an open generic, which is where the type arguments are generic parameters - e.g, given:
class MyType<T> : List<T> { }
Then List<T> is an open generic with the generic type definition List<>, because T is a generic parameter which will not be closed till MyType<T> is referenced with a concrete type argument, such as int or string.
Finally, just because a bunch of generic types share the same common name, e.g. Func<>, Func<,>, and Func<,,> it does not mean they are in any way related. At the type level, there is no explicit connection, which is why you have to check for all these type identities, and why there is no common 'base' as you put it. If they all had a common interface or base class, however, then you could - by checking for compatibility with that interface or base type.
Given a generic type definition, you can construct generic types using MakeGenericType, as has been mentioned by Jeffrey Zhang.
No, you can't, There is not a base type of a Gerneric Type. If you want to get a specific generic type by type parameters, You can use MakeGenericType. For example:
//get Func<int, string> type
typeof(Func<>).MakeGenericType(typeof(int), typeof(string));
If you want to get a Generic Type from specified generic type, You can use GetGenericTypeDefinition. For example:
//get Func<,> type
typeof(Func<int, string>).GetGenericTypeDefinition();
It is Because Func< A, B > does not inherit from Func<> It is a generic based on Func<,>.
However, you will notice that
typeof(Func<int, int>).FullName // equals "System.Func`2...
typeof(Func<int, int, int>).FullName // equals "System.Func`3...
It is a bit ugly but you could use something like
YourType.FullName.StartsWith("System.Func")
Hope it helps
Edit:
Why not use YourType.GetGenericTypeDefinition()?
Because typeof(Func<int, int>).GetGenericTypeDefinition() returns Func<,>
and typeof(Func<int, int, int>).GetGenericTypeDefinition() return Func<,,>.
Func<,> and Func<,,> are not the same Type.

Casting list of objects to List vs IList

Just came across this:
Func<List<object>> foo = () => new List<object>();
List<string> s = (List<string>)foo();
IList<string> s1 = (IList<string>)foo();
Compiler complains about casting to List (makes sense), but says nothing about IList. Makes me wonder why is that?
The compiler knows that a List<X> cannot be a List<Y>.
It therefore gives a compiler error.
However, the second cast could succeed if the List<X> is actually some derived class that also implements IList<Y>.
You will only get a compile-time error from a cast if neither type is an interface, or if one type is an unrelated interface and the other type is sealed (or a struct).
To quote the spec (ยง6.4.2)
The explicit reference conversions are:
From object and dynamic to any other reference-type.
From any class-type S to any class-type T, provided S is a base class of T.
From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
From any interface-type S to any interface-type T, provided S is not derived from T.
[snip]
(emphasis added)
The provided... clauses exclude conversions that are actually implicit.
An object that is known to be a List<object> might implement IList<string> as well as IList<object>, so it's possible that the cast can succeed. It can't in this case because we know that the statement is simply new List<object>(), but the compiler doesn't consider that. You might've extended List<T> and implemented the other, e.g.
// not recommended, but second cast works
public class MyWeirdList : List<object>, IList<string>
An object that is known to be a List<object> cannot possibly also be a List<string>, because you can only inherit from a single type.
public class MyWeirdList : List<object>, List<string> // compiler error
If List<T> were sealed, both casts would be invalid, because then the compiler would know for sure that the class couldn't implement IList<string>. You can try this by using this class instead:
public sealed class SealedList<T> : List<T> { }
The first line fails at compile time, the second gives an "Unable to cast object of type 'System.Collections.Generic.List1[System.Object]' to type 'System.Collections.Generic.IList1[System.String]'." exception during runtime.
If you look at this question (Cast IList<string> to IList<object> fails at runtime), the answer clarifies why this compile works and also provides an example for a class that could satisfy the conditions provided.

Difference between covariance and upcasting

What is the difference between covariance and upcasting, or, more specifically, why are they given different names?
I've seen the following example referred to as 'upcasting':
string s = "hello";
object o = s; //upcast to 'string' to 'object'
Whereas, the following I have seen called 'covariance':
string[] s = new string[100];
object[] o = s;
IEnumerable<string> ies = new List<string>();
IEnumerable<object> ieo = ies;
Now, to my untrained eye, covariance seems to be the same as upcasting, except that it refers the casting of collections. (And of a similar statement can be made regarding contravariance and downcasting).
Is it really that simple?
Now, to my untrained eye, covariance seems to be the same as upcasting, except that it refers the casting of collections. (And of a similar statement can be made regarding contravariance and downcasting).
Is it really that simple?
Covariance isn't about upcasting, although I can see why you think it's related.
Covariance is about the following very simple idea. Let's say you have a variable derivedSequence of type IEnumerable<Derived>. Let's say you have a variable baseSequence of type IEnumerable<Base>. Here, Derived derives from Base. Then, with covariance, the following is a legal assignment, and an implicit reference conversion occurs:
baseSequence = derivedSequence;
Note that this is not upcasting. It is not the case that IEnumerable<Derived> derives from IEnumerable<Base>. Rather, it is covariance that allows you to assign the value of the variable derivedSequence to the variable baseSequence. The idea is that variables of type Base can be assigned from objects of type Derived, and since IEnumerable<T> is covariant in its parameter, objects of type IEnumerable<Derived> can be assigned to variables of type IEnumerable<Base>.
Of course, I haven't yet really explained what covariance is. In general, covariance is about the following simple idea. Let's say you have a mapping F from types to types (I'll denote this mapping by F<T>; given a type T its image under the mapping F is F<T>.) Let's say that this mapping has the following very special property:
if X is assignment compatible with Y, then F<X> is assignment compatible with F<Y> as well.
In this case, we say that F is covariant in its parameter T. (Here, to say that "A is assignment compatible with B" where A and B are reference types means that instances of B can be stored in variables of type A.)
In our case, IEnumerable<T> in C# 4.0, an implicit reference conversion from instances of IEnumerable<Derived> to IEnumerable<Base> if Derived is derived from Base. The direction of assignment compatibility is preserved, and this is why we say that IEnumerable<T> is covariant in its type parameter.
Casting refers to changing the static type of objects and expressions.
Variance refers to the interchangeability or equivalence of types in certain situations (such as parameters, generics, and return types).
IEnumerable<string> is not derived from IEnumerable<object>, so the cast between them is not upcasting. IEnumerable is covariant in its type parameter and string is derived from object, so the cast is allowed.
The reason they are different concepts is that, unlike upcasting, covariance is not always allowed. It would have been easy for the designers of the type-system to make IList<Cat> be considered as "derived" from IList<Animal>, but then we run into problems:
IList<Cat> cats = new List<Cat>();
IList<Animal> animals = cats;
animals.Add(new Dog()); //Uh oh!
If this were allowed, now our cats list would contain a Dog!
In contrast, the IEnumerable<T> interface has no way of adding elements, so this is perfectly valid (in C# 4.0):
IList<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;
//There's no way to add things to an IEnumerable<Animal>, so here we are ok
Thie blog post below has a good explanation of it:
http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
From what I can gather covariance removes the need for explicit downcasting subsequent to a previous upcast. Typically if you upcast an object you can only access the base type methods and attributes, with covariance it seems you can imply the downcast by replacing lesser derived types with more derived types in the more derived class declaration.

IList<T> vs IEnumerable<T>: Why is this assignment invalid?

Elephant : Animal....
IList<Elephant> elephants = new List<Elephant>();
IEnumerable<Animal> animalList = elephants;
this works fine but..
IList<Elephant> elephants = new List<Elephant>();
IList<Animal> animalList = elephants;
throws an error. Why is that?
If this
IList<Elephant> elephants = new List<Elephant>();
IList<Animal> animalList = elephants;
were possible you could then do this
animalList.Add(new Animal());
but animalList is really a reference to the same referrent as elephants. And since elephants is an IList<Elephant> you'd be trying to add an instance of Animal to an collection that can only contain instances of Elephant.
The reason that it is possible for IEnumerable<T> is that IEnumerable<T> is covariant in the type parameter T. This is because T only appears in "out" positions in the interface IEnumerable<T>. Since you're only consuming instances of T from the IEnumerable<T>, it is safe to assign instances of IEnumerable<Derived> to variables of type IEnumerable<Base>. Anything that comes out of IEnumerable<Derived> is a Base and this is why something that implements IEnumerable<Derived> can be used as a IEnumerable<Base> safely. This is why it is safe to assign an instance of IEnumerable<Elephant> to a variable of type IEnumerable<Animal>.
But you get in trouble with IList<T> because IList<T> is not covariant in the type parameter T. The issue here is that T appears in "in" positions in the interface IList<T>. So if you could assign instances of IList<Derived> to variables of type IList<Base>, then you could try to stick instances of Base into the IList<Base> which would really be trying to stick instances of Base into an instance of IList<Derived> and that is clearly not safe to do. This is exactly the issue that we just ran into with IList<Elephant> and IList<Animal>.
Note that IList<T> is also not contravariant in the type parameter T. This is because T appears in "out" positions in the interface IList<T>. If you could assign instances of IList<Base> to a variable of type IList<Derived> then you could try to grab an instance of Derived out of the IList<Derived> which would be trying to grab an instance Derived out of an instance of IList<Base> and that is clearly absurd.
This is called covariance and contravariance.
I won't go into details but you can read about it.

Categories

Resources