在我班上我有
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),则会抛出异常。
编辑:如果无法做到这一点,是否有其他可行的解决方案?
答案 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#
是一种基于语言设计的类型安全,因此列表的使用者无法向其中注入非SomethingElse
或SomethingMore
的类型。
如果你需要约束一些从通用接口派生的类型,比如SomethingElse
,我会去
隐藏公开List
本身的属性
private List<ISomething> ListOfSomethings {get; set;}
添加公共成员函数,例如FromList
public void FromList(List<SomethingElse> somethings)
{
ListOfSomethings = somethings;
}
此函数成为将列表分配给类的唯一方法,并且考虑到它只接受某种类型的列表,您将被创建所需的限制。
答案 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。