Anonymous
Anonymous

Reputation: 9648

How to cast list of X to list of Y in C#?

I have 2 base classes FirstBase and SecondBase. I also have 2 class derive from them, DerivedFirst and DerivedSecode and both of them has almost of same property. Source code is like below.

public abstract class FirstBase
{
    //some method
}

public abstract class SecondBase
{
    //some method
}

public class DerivedFirst : FirstBase
{
    //override methods of its parent

    public static implicit operator DerivedFirst(DerivedSecond second)
    {
        //doing some logic here
    }
}

public class DerivedSecond : SecondBase
{
    //override methods of its parent

    public static implicit operator DerivedSecond(DerivedFirst first)
    {
        //doing some logic here
    }
}

From this code I can create instance of DerivedFirst and assign to DerivedSecond without any problem. However when I try to convert list of them like code below, It has no result.

List<DerivedFirst> firstList;
List<DerivedSecond> secondList;

//doing some operation here

List<DerivedSecod> test = firstList.Cast<DerivedSecond>(); // don't have any output here.

How can I convert firstList to List()?

Upvotes: 4

Views: 196

Answers (3)

Florian Reischl
Florian Reischl

Reputation: 3866

Your desired behavior does not work. The static implicit operator is nothing more than a fancy way to write code. DerivedFirst cannot really be casted into a DerivedSecond.

The call of FirstList.Cast<DerivedSecond> works since LINQ streams over the input list while accessing its items. As soon as you access any item in the resulting IEnumerable<DerivedSecond> you get an InvalidCastException.

Try this Visual Studio Test code to see what I mean:

   [TestClass]
   public class UnitTest1 {
      class DerivedA {
         public static implicit operator DerivedA(DerivedB b) {
            return new DerivedA();
         }
      }
      class DerivedB {
         public static implicit operator DerivedB(DerivedA a) {
            return new DerivedB();
         }
      }

      [TestMethod]
      public void TestMethod1() {
         IList<DerivedA> lista = new List<DerivedA> {
            new DerivedA()
         };
         var casted = lista.Cast<DerivedB>();

         try {
            DerivedB b = casted.First();
            Assert.Fail();
         } catch (InvalidCastException) {
            // exception will be thrown
         }
      }
   }

Edit: The only solution to "cast" the objects is to use the "Select" method:

var casted = lista.Select(a => (DerivedB)a);

Upvotes: 2

abhishek
abhishek

Reputation: 2992

You have just talked about Variance. C# actually introduces Co-variance in .NET 4.0. So if you are in C# 4.0, you can easily do this using out operator in your list.

Check my article

http://www.abhisheksur.com/2010/06/c-40-features.html

I hope this would help you.

Otherwise you can use Loop to cast each individual objects to create a separate list of that type.

Upvotes: 0

Mark Byers
Mark Byers

Reputation: 838376

User-defined implicit conversions are considered only at compile time, not at run-time (source). You can use Select instead:

List<DerivedSecond> foo = firstList.Select(x => (DerivedSecond)x).ToList();

Upvotes: 4

Related Questions