代码之家  ›  专栏  ›  技术社区  ›  David

如何将C#中的X列表转换为Y列表?

  •  4
  • David  · 技术社区  · 14 年前

    我有两个基类FirstBase和SecondBase。我还有两个派生自它们的类,DerivedFirst和DerivedSecode,它们的属性几乎相同。源代码如下。

    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
        }
    }
    

    从这段代码中,我可以创建DerivedFirst的实例并毫无问题地分配给DerivedSecond。然而,当我试图像下面的代码一样转换它们的列表时,却没有结果。

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

    3 回复  |  直到 14 年前
        1
  •  4
  •   Community Mr_and_Mrs_D    7 年前

    只有在编译时才考虑用户定义的隐式转换,而不是在运行时( source ). 您可以改用Select:

    List<DerivedSecond> foo = firstList.Select(x => (DerivedSecond)x).ToList();
    
        2
  •  2
  •   Tim Cooper    13 年前

    你想要的行为行不通。这个 static implicit operator

    FirstList.Cast<DerivedSecond> 因为LINQ在访问输入列表项时在输入列表上进行流处理。一旦您访问结果中的任何项目 IEnumerable<DerivedSecond> 你得到一个 InvalidCastException .

       [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
             }
          }
       }
    

    编辑 : “投射”对象的唯一解决方案是使用“选择”方法:

    var casted = lista.Select(a => (DerivedB)a);
    
        3
  •  0
  •   Community Mr_and_Mrs_D    4 年前

    你刚才谈到了方差。C实际上在.NET4.0中引入了协方差。因此,如果您使用的是C#4.0,那么您可以使用列表中的out操作符轻松地完成此操作。

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

    我希望这对你有帮助。

    否则,可以使用循环来强制转换每个单独的对象,以创建该类型的单独列表。