JSB*_*ոգչ 6 c# generics interface constraints
允许以下内容的目的是什么?
class A<T> where T : IFoo {
private T t;
A(T t) { this.t = t; }
/* etc */
}
Run Code Online (Sandbox Code Playgroud)
这与仅仅声明A
需要一个IFoo
需要它的地方有什么不同?
class A {
private IFoo foo;
A(IFoo foo) { this.foo = foo; }
/* etc */
}
Run Code Online (Sandbox Code Playgroud)
我能看到的唯一区别是,在第一种情况下,我保证都认为A<T>
将始终与一个实例化T
实现IFoo
和所有对象的A
将是相同的基本类型.但对于我的生活,我无法弄清楚为什么我需要这样的约束.
两个示例的主要区别在于,class A
无论何时将变量定义为T,您都可以使用该变量上的所有属性/函数,这些属性/函数也在IFoo中定义.
然而,在class B
该IFoo
只是为泛型类型参数的名称,因此,只要你声明一个变量的类里面的IFoo
,就好像它是一个你只能用它object
的类型.
例如,如果
public interface IFoo
{
int Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后你可以做到这一点 class A
class A<T> where T : IFoo
{
public void DoSomething(T value)
{
value.Value++;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您尝试相同的操作,class B
则会遇到编译器错误,该类型IFoo
不包含属性Value
或类似内容.原因是<IFoo>
B类只是一个名称而且与界面无关,你可以把它称为任何你喜欢的东西.
更新:
class B {
private IFoo foo;
B(IFoo foo) { this.foo = foo; }
/* etc */
}
Run Code Online (Sandbox Code Playgroud)
这个构造确实基本相同,除非IFoo
再次暴露回外部,请考虑两个类中的以下属性
A类:
public T Foo { get { return foo; }}
Run Code Online (Sandbox Code Playgroud)
B级:
public IFoo Foo { get { return foo; }}
Run Code Online (Sandbox Code Playgroud)
现在考虑用C类初始化两个类,定义为C类
public class FooClass : IFoo
{
public int Value { get; set; }
public int SomeOtherValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后考虑定义为2个变量
var foo = new FooClass();
var a = new A<FooClass>(foo);
var b = new B(foo);
Run Code Online (Sandbox Code Playgroud)
现在设置你可以做的SomeOtherValue
使用a
a.Foo.SomeOtherValue = 2;
Run Code Online (Sandbox Code Playgroud)
而你必须这样做
((FooClass)b.Foo).SomeOtherValue = 2;
Run Code Online (Sandbox Code Playgroud)
希望有意义;-)
编辑:起初我以为你很愚蠢:第一个例子肯定无法编译。只有在自己尝试过(并且看到它确实可以编译)之后,我才意识到Doggett 已经指出的内容:您的class B<IFoo>
示例实际上与接口没有关系IFoo
;它只是一个泛型类型,其类型参数恰好被调用IFoo
。
也许您已经意识到了这一点,并且您确实在问:“为什么我要限制泛型类型参数?” 如果是这样的话,那么我认为其他答案已经在某种程度上解决了这个问题。但听起来你好像在问,“为什么我要这样定义我的类型,而不是这样(因为它们实际上是相同的)?” 答案很简单:它们不一样。
\n\n现在,这是另一个问题\xe2\x80\x94,你没有问,但我最初打算回答这个问题;)
\n\n为什么要定义这样的类型:
\n\nclass A<T> where T : IFoo\n{\n T GetFoo();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n...而不是这个?
\n\nclass A\n{\n IFoo GetFoo();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n我想到的一个原因是(因为它类似于我过去处理过的场景):您设计的不是一个类,而是一个小的类层次结构,并且IFoo
只是“基线”接口您的所有类都需要,而有些类可能会利用特定的实现或更多派生的接口。
这是一个愚蠢的例子:
\n\nclass SortedListBase<T, TList> where TList : IList<T>, new()\n{\n protected TList _list = new TList();\n\n // Here\'s a method I can provide using any IList<T> implementation.\n public T this[int index]\n {\n get { return _list[index]; }\n }\n\n // Here\'s one way I can ensure the list is always sorted. Better ways\n // might be available for certain IList<T> implementations...\n public virtual void Add(T item)\n {\n IComparer<T> comparer = Comparer<T>.Default;\n for (int i = 0; i < _list.Count; ++i)\n {\n if (comparer.Compare(item, _list[i]) < 0)\n {\n _list.Insert(i, item);\n return;\n }\n }\n\n _list.Add(item);\n }\n}\n\nclass SortedList<T> : SortedListBase<T, List<T>>\n{\n // Here is a smarter implementation, dependent on List<T>\'s\n // BinarySearch method. Note that this implementation would not\n // be possible (or anyway, would be less direct) if SortedListBase\'s\n // _list member were simply defined as IList<T>.\n public override void Add(T item)\n {\n int insertionIndex = _list.BinarySearch(item);\n\n if (insertionIndex < 0)\n {\n insertionIndex = ~insertionIndex;\n }\n\n _list.Insert(insertionIndex, item);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
201 次 |
最近记录: |