在通用版本

时间:2015-11-09 14:46:18

标签: c# .net generics

我有一个界面说明:

public interface IMyType<T> where T: IMySubType {
    event EventHandler<IMyType<T>, EventArgs<T>> OnSomething;
    IEnumerable<T> AvailableThings{get;}
    void Start();
}

我是List<IMyType<IMySubType>>,如何在此列表中添加IMyType<SubTypeImplementation>? (SubTypeImplementation界面中的IMySubType herits。

我尝试将我的T泛型类型作为协变,但它似乎不能使用此类型作为事件的接口(不确定知道原因)。

那么,我如何在列表的每个元素上存储,迭代和调用start方法?

因为目前我的另一个选择是创建一个没有通用性的新接口,并进行双重实现(因为在大多数情况下我需要具有这种通用性。

2 个答案:

答案 0 :(得分:0)

这个怎么样:

<table class="table-c">
  <tr>
    <td style="width: 10%">REFERENCE NO.</td>
    <td style="width: 30%">DESCRIPTION</td>
    <td style="width: 10%">Invoice DATE</td>
    <td style="width: 10%">INVOICE AMOUNT</td>
    <td style="width: 20%">DISCOUNT TAKEN</td>
    <td style="width: 20%">AMOUNT PAID</td>
  </tr>
  <tr style="height: 200px">
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</table>
<table class="table-c">
  <tr>
    <td style="width: 20%">CHECK DATA</td>
    <td style="width: 10%">CHECK NO.</td>
    <td style="width: 40%">PAYEE</td>
    <td style="width: 10%">DISCOUNT TAKEN</td>
    <td style="width: 20%">CHECK AMOUNT</td>                                
  </tr> 
  <tr style="height: 200px">
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>                           
</table>

您的列表类型为public interface IMyType { } public interface IMyType<T> : IMyType where T : IMySubType { event EventHandler<IMyType<T>, EventArgs<T>> OnSomething; IEnumerable<T> AvailableThings{get;} void Start(); }

List<IMyType>

当然,缺点是您需要在列表中强制转换每个元素才能使用它:

List<IMyType> myList = new List<IMyType>();
myList.Add(implementation1); // implementation1 is of type IMyType<SubTypeImplementation>
myList.Add(implementation2); // implementation2 is of type IMyType<SubTypeImplementation2>

无论如何,在这种情况下我不会使用泛型。

我的var impl = (IMyType<SubTypeImplementation>)list[0]; impl.Start(); 看起来像这样:

IMyType

答案 1 :(得分:0)

  

如何在此列表中添加IMyType<SubTypeImplementation>

IMyType需要协变才能发挥作用。协变意味着泛型类型只能 包含在函数的输出中。由于您的界面包含EventHandler,它将泛型类型作为输入的一部分,因此您的界面不能协变。

让我们更改您的界面名称以了解原因。假设你经营一个动物园,并希望区分&#34;仅查看&#34;来自&#34;正常&#34;的笼子笼子里。所以你有两个接口:

IViewOnlyCage<out T>
{
    public T View();
}

ICage<T>
{
    public Add(T animal);
}

现在考虑两个&#34;列表&#34;笼子:

List<IViewOnlyCage<IAnimal>> list1;
List<ICage<IAnimal>> list2;

我填写列表:

list1.Add(new Cage<Tiger>());
list1.Add(new Cage<Deer>());

在第一种情况下,只有视图的笼子列表是完全合理的。每个笼子都包含某种类型的动物,因此这两种动物没有危险结合在一起。

但考虑第二种方法 - 使用Add方法,我可以这样做:

list2.Add(new Cage<Tiger>());

ICage<IAnimal> cage = list2[0];  // a reference to the tiger cage
cage.Add(new Deer());  //uh-oh... bad news for the deer

由于您的界面包含间接输入,因此可能会出现这样的情况:

List<IMyType<IMySubType>> list = new List<IMyType<IMySubType>>();

list.Add(new IMyType<SubTypeImplementation>());

IMyType<IMySubType> item = list[0];  // seems OK

item.OnSomething += new EventHandler(IMyType<SecondSubType>, EventArgs<SecondSubType>);   

实际泛型类型为SubTypeImplementation,而非SecondSubType,因此您遇到类型冲突。

最简单的更改似乎是将事件处理程序移动到另一个接口。然后,您可以IMyType协变并拥有List<IMyType<IMySubType>>