2008-10-09 37 views
3

我试图向他人展示他们创建的疯狂情况下的界​​面使用。它们在列表中有几个不相关的对象,并且需要对每个对象的两个字符串属性执行操作。我指出,如果他们将属性定义为接口的一部分,他们可以使用接口对象作为作用于其上的方法参数的类型;例如:有没有办法将通用列表转换为接口/基类类型列表?

void PrintProperties(IEnumerable<ISpecialProperties> list) 
{ 
    foreach (var item in list) 
    { 
     Console.WriteLine("{0} {1}", item.Prop1, item.Prop2); 
    } 
}

这似乎是这一切都很好,但需要对工作的名单都没有(也不应该)与接口的类型参数声明。但是,它似乎并不像您可以投射到不同的类型参数。例如,这个失败,我不明白为什么:

using System; 
using System.Collections.Generic; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Test> myList = new List<Test>(); 
      for (int i = 0; i < 5; i++) 
      { 
       myList.Add(new Test()); 
      } 

      PrintList((IEnumerable<IDoSomething>)myList); 
     } 

     static void PrintList(IEnumerable<IDoSomething> list) 
     { 
      foreach (IDoSomething item in list) 
      { 
       item.DoSomething(); 
      } 
     } 
    } 

    interface IDoSomething 
    { 
     void DoSomething(); 
    } 

    public class Test : IDoSomething 
    { 
     public void DoSomething() 
     { 
      Console.WriteLine("Test did it!"); 
     } 
    } 
}

可以使用Enumerable.Cast<T>成员要做到这一点,但我一直在寻找可能的工作在.NET 2.0和方法。看来这应该是可能的;我错过了什么?

回答

5

的问题与方法,而不是与它怎么叫.....

void PrintProperties<SP>(IEnumerable<SP> list) where SP: ISpecialProperties 
{ 
    foreach (var item in list) 
    { 
     Console.WriteLine("{0} {1}", item.Prop1, item.Prop2); 
    } 
} 
+0

正是我刚写的东西。 – 2008-10-09 19:24:27

+0

我偶然发现它,并且也要发布它。这有点奇怪,但我可以理解为什么它是这样;你必须指定类型是可施放的。 – OwenP 2008-10-09 19:25:22

5

失败的原因是因为仿制药并不在C#中(还)表现出差异。

而对于修为的IEnumerable < T>,不过,试试这个:

public static IEnumerable<TBase> SafeConvert<TBase, TDerived>(IEnumerable<TDerived> source) 
    where TDerived : TBase 
{ 
    foreach (TDerived element in source) 
    { 
     yield return element; // Implicit conversion to TBase 
    } 
} 

编辑:现有的其他答案是比上述的这种特殊情况比较好,但我会离开这里这是如果你确实需要“转换”序列,这是一个非常有用的东西。

+0

啊Skeet先生 - 非常棒的例子,非常帮助我,谢谢! – BenAlabaster 2009-01-29 00:29:37

1

您可以在列表中使用foreachforeach做内置演员。所以,如果你把循环出来的功能,你可以写类似

List<Test> myList = new List<Test>(); 
for (int i = 0; i < 5; i++) 
{ 
    myList.Add(new Test()); 
} 

foreach (IDoSomething item in myList) 
{ 
    item.DoSomething(); 
} 
+0

需要注意的一点(在foreach中强制转换),但并不涉及将各种派生类型的列表传递给同一函数以防函数必须执行其他操作。 – 2008-10-09 21:12:25

-1

这不回答你的问题(或我猜:)锻炼的观点,但我只是使用反射在这通过将特殊属性附加到感兴趣的属性。

相关问题