26

我正在尝试找到使用通用接口的通用列表作为变量的正确方法。

这是一个例子。这可能不是最好的,但希望你能明白这一点:

public interface IPrimitive<T>
{
     T Value { get; }
}

然后在另一个类中,我希望能够声明一个变量,该变量包含一个IPrimitive<T>为任意实现的对象列表T

// I know this line will not compile because I do not define T   
List<IPrimitive<T>> primitives = new List<IPrimitives<T>>;

primitives.Add(new Star());   // Assuming Star implements IPrimitive<X>
primitives.Add(new Sun());    // Assuming Sun implements IPrimitive<Y>

请注意,列表中每个条目的TinIPrimitive<T>可能不同。

关于如何建立这种关系的任何想法?替代方法?

4

4 回答 4

29
public interface IPrimitive
{

}

public interface IPrimitive<T> : IPrimitive
{
     T Value { get; }
}

public class Star : IPrimitive<T> //must declare T here
{

}

那么你应该能够拥有

List<IPrimitive> primitives = new List<IPrimitive>;

primitives.Add(new Star());   // Assuming Star implements IPrimitive
primitives.Add(new Sun());    // Assuming Sun implements IPrimitive
于 2010-12-23T21:28:58.903 回答
11

约翰是对的。

我是否还建议(如果您使用 C# 4)使您的界面协变?

public interface IPrimitive<out T>
{
     T Value { get; }
}

当您需要从列表中删除某些内容时,这可以为您节省一些麻烦。

于 2010-12-23T21:29:02.967 回答
3

你说它不起作用,因为你没有定义T. 所以定义它:

public class Holder<T>
{
    public List<IPrimitive<T>> Primitives {get;set;}
}
于 2010-12-23T21:27:14.517 回答
1

这是 c# 语言中最复杂的元素之一,尽管它对于构建定义良好的组件非常重要。因此,c# 功亏一篑。但是,绝对有可能完成这项工作。

诀窍是有3个部分:

  1. 包含接口所有要求的非通用接口。
  2. 实现非泛型接口并根据需要执行类型转换的泛型抽象类。
  3. 实现具有适当类型结果的通用抽象类的类

例如:

public interface INonGenericInterface{
    void Execute(object input);
    object GetModel();
}

public abstract class IGenericInterfaceBase<T> : INonGenericInterface{
    void INonGenericInterface.Execute(object input){
        Execute((T) input);
    }

    object INonGenericInterface.GetModel(){
        return GetModel();
    }

    protected abstract void Execute(T input);
    protected abstract T GetModel();
}

public class ImplementingClass : IGenericInterfaceBase<ModelClass>{
    protected override void Execute(ModelClass input){ /*Do something with the input */ }  
    protected override ModelClass GetModel(){ return new ModelClass();}
}

//Extras for demo
public class ModelClass { }
public class ModelClass2 { }

public class ImplementingClass2 : IGenericInterfaceBase<ModelClass2>
{
    protected override void Execute(ModelClass2 input) { /*Do something with the input */ }
    protected override ModelClass2 GetModel() { return new ModelClass2(); }
}

var agi = new INonGenericInterface[] { new ImplementingClass(), new ImplementingClass2() };
agi[0].Execute(); var model = agi[0].GetModel();
agi[1].Execute(); var model2 = agi[1].GetModel();
//Check the types of the model and model2 objects to see that they are appropriately typed.

这种结构在相互协调类时非常有用,因为您可以指示一个实现类将使用多个类,并通过类型检查验证每个类是否遵循已建立的类型预期。此外,您可能会考虑为非泛型类使用实际类而不是对象,以便您可以对各种非泛型调用的结果执行函数。使用相同的设计,您可以让这些类成为具有自己实现的泛型类,从而创建极其复杂的应用程序。

致 OP:请考虑更改已接受的答案,以提高对正确方法的认识,因为所有先前陈述的答案都因各种原因而不足,并且可能给读者留下了更多问题。这应该处理与集合中的泛型类相关的所有未来问题。

于 2021-11-28T19:46:44.067 回答