是否可以在List <interface>?</interface>上施加类型约束

时间:2014-12-29 21:43:10

标签: c# .net

在我班上我有

class MyClass : IMyInterface
{

//I want MyClass only to be able to accept object of type List<SomethingElse>
public List<ISomething> ListOfSomethings {get; set;}

}

interface IMyInterface{

List<ISomething> ListOfSomethings {get; set;}

}

class SomethingElse : ISomething{

}

class SomethingMore : Isomething{

}

基本上我想知道是否可以约束列表在MyClass中使用的类型,因此如果有人尝试将其编码为错误类型(即List of SomethingMore),则会抛出异常。

编辑:如果无法做到这一点,是否有其他可行的解决方案?

4 个答案:

答案 0 :(得分:5)

您可以使用T限制约束列表项的T(类型)(以及任何其他where):

有关详细信息,请参阅Constraints on Type Parameters

<强>接口

interface ISomething { }

仅允许使用实现接口T的{​​{1}}。

ISomething

<强>类

interface IMyInterface<T> where T : ISomething
{
    List<T> ListOfSomethings { get; set; }
}

您可以限制class SomethingElse : ISomething { } class SomethingMore : ISomething { } class MyClass1 : IMyInterface<SomethingElse> { public List<SomethingElse> ListOfSomethings { get; set; } } class MyClass2 : IMyInterface<SomethingMore> { public List<SomethingMore> ListOfSomethings { get; set; } } 适合您的人。这里例如关于类本身。 这只允许T

SomethingElse

class MyClass3<T> : IMyInterface<T> where T : SomethingElse { public List<T> ListOfSomethings { get; set; } } 的示例:

Dictionary

如果你不是每次都没有投出它,那么我目前唯一能想到的解决方案是创建自定义字典并封装演员:

var dic = new Dictionary<string, IMyInterface<ISomething>>();
dic.Add("MyClass1", (IMyInterface<ISomething>)new MyClass1());
dic.Add("MyClass2", (IMyInterface<ISomething>)new MyClass2());

答案 1 :(得分:2)

//I want MyClass only to be able to accept object of type List<SomethingElse>

然后你不能将它定义为List<ISomething>,而是使用不同的界面甚至是具体的类型。如果将其定义为List<ISomething>,则自动接受任何内容,即实现ISomething接口。没有办法解决这个问题。

答案 2 :(得分:1)

C#是一种基于语言设计的类型安全,因此列表的使用者无法向其中注入非SomethingElseSomethingMore的类型。

如果你需要约束一些从通用接口派生的类型,比如SomethingElse,我会去

  1. 隐藏公开List本身的属性

    private List<ISomething> ListOfSomethings {get; set;}
    
  2. 添加公共成员函数,例如FromList

    public void FromList(List<SomethingElse> somethings)
    {
        ListOfSomethings = somethings;
    }
    
  3. 此函数成为将列表分配给类的唯一方法,并且考虑到它只接受某种类型的列表,您将被创建所需的限制。

答案 3 :(得分:1)

您可以使用 explicit interface implementation

执行此操作
class MyClass : IMyInterface
{
    List<ISomething> IMyInterface.ListOfSomethings
    {
        get { return this.ListOfSomethings.Cast<ISomething>().ToList(); }
        set { this.ListOfSomethings = value.Cast<SomethingMore>().ToList(); }
    }

    List<SomethingMore> ListOfSomethings { get; set; } 
}

请注意,建议不要进行此类限制,因为这违反了Liskov substitution principle:您的类的用户可能正在使用IMyInterface接口,并且不知道其类型受到限制。

另一个问题是在接口中暴露这样的List<T>:调用者可以调用列表方法,如添加或删除,也可以设置整个List实例。这可能不是你想要的。如果要公开只读集合,请使用带有数组或可枚举类型的getter。