Cannot convert source type 'List<Person>' to IList<ISomething>
Solution 1
This is called covariance. Eric Lippert and Jon Skeet (among others) gave some nice explanations of covariance (and its twin, contravariance) in answers to this question: Difference between Covariance & Contra-variance
Very basically, you can enumerate over a list of Person
just like you would do over a list of ICloneable
, no problem could occur because you can't change the enumeration. But you can't assign your list of Person
to a list of ICloneable
because then you could later try, for example, to insert some other derivative of ICloneable
in it, which would result in a strong violation of type-safety.
Solution 2
public interface IList<T> : ICollection<T>,
IEnumerable<T>, IEnumerable
public interface IEnumerable<out T> : IEnumerable
Notice the out
in IEnumerable
? IEnumerable<T>
is covariant
Solution 3
I had a different answer, which was wrong. I apologize. Thanks Matt for pointing this out.
The error message is quite misleading. It suggests a cast will work, but does not. The problem is that the conversion of Person to ICloneable may require adjusting the pointer so that the virtual function table is correct for a generic ICloneable. That means every element in the list may need an adjustment. The real fix is to use ToList:
IList<ICloneable> clonablesA = people.ToList<ICloneable>();
Ignore some of the comments below, since I completely erased my first answer.
Xinbi
I've been a software engineer for over 20 years in the Portland, Oregon area. I've done online banking, anti-virus software and mobile apps.
Updated on June 14, 2022Comments
-
Xinbi almost 2 years
This might be a pretty simple question, but something doesn't make sense to me.
Given this class:
public class Person : ICloneable { public object Clone() { Console.WriteLine("Hello, world"); return new Person(); } }
Why is this ok?
List<Person> people = new List<Person> { new Person() }; IEnumerable<ICloneable> clonables = people;
But this isn't?
List<Person> people = new List<Person> { new Person() }; IList<ICloneable> clonables = people;
Why is it I can assign to an IEnumerable IClonable, but not an IList ICloneable?
-
Yinda Yin over 9 yearsDon't sign your posts. They are already signed; see? --------------->
-
Xinbi over 9 yearsEven an explicit cast doesn't work. IList<ICloneable> cloneables = (IList<ICloneable>)people;
-
Servy over 9 yearsThe error message does not say that an explicit cast exists, nor is one valid in this context.
-
KC-NH over 9 yearsUsing VS 2013, the error message I see is: Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<Cloneable.Person>' to 'System.Collections.Generic.IList<System.ICloneable>'. An explicit conversion exists (are you missing a cast?) C:\Users\Ken\Documents\Visual Studio 2013\Projects\Samples\Cloneable\Cloneable\Program.cs 29 45 Cloneable
-
Matt Burland over 9 yearsThe explicit cast won't work. It will trade your compile time error for a run-time exception (
InvalidCastException
). -
Matt Burland over 9 years@KC-NH: Where you try to do the cast, obviously.