C#中的通用约束,T是相同的TSomethingElse,对吧?(Generic constraints in C#, T is the same TSomethingElse, right?)
我经常看到:
public interface IFoo<TWidget> where TWidget : ISomethingElse { }
在这种情况下,TWidget与使用泛型T相同,是否正确? 我发现这个令人惊讶的难以谷歌或在规格中找到。 我99%肯定T +的其他角色与T说的相同,但是想绝对确定。
I often see:
public interface IFoo<TWidget> where TWidget : ISomethingElse { }
In this case, TWidget is the same as using the generic T, correct? I'm finding this surprisingly hard to google or find in the specs. I'm 99% sure that T + any other characters is the same as saying just T, but wanted to be absolutely sure.
原文:https://stackoverflow.com/questions/6009689
更新时间:2020-11-02 21:11
最满意答案
泛型类型参数的名称可以通过任何有效的标识符名称。
在大多数文档中,您确实可以在TWidget
找到T
来自MSDN:
使用描述性名称命名泛型类型参数,除非单个字母名称完全是自解释的,并且描述性名称不会添加值。
The name of the generic type parameter can by any valid identifier name.
In most documentation you would indeed find T
where you put TWidget
.
From MSDN:
Do name generic type parameters with descriptive names, unless a single letter name is completely self explanatory and a descriptive name would not add value.
2011-05-15
不,这不能通过设计工作,因为这意味着IAwesome的合同不会(完全)满意。 只要IncrediblyAwesome<T>实现IAwesome ,就可以这样做: IAwesome x = new IncrediblyAwesome<Something>()
很明显,由于额外的限制,这是行不通的,因为IAwesome的用户无法知道对它的限制。 在你的情况下,我能想到的唯一解决方案是(做运行时检查): interface IAwesome { // assuming the same interfa
...
请注意,C#4确实有额外的方差支持,但由于各种原因(既有“in”又有“out”方法,并且是一个类)它不适用于List<T>情况。 然而,我认为解决这个问题的方法是这样的: interface IState { // non-generic
object Value { get; } // or whatever `State<Thing>` needs
}
class State<T> : IState {
public T Value { get { ...} } // or w
...
这是偶尔要求的功能。 正如我喜欢指出的那样,除非有人设计,规格,实施,测试,文档和发送功能,否则所有功能都不会实现。 到目前为止,没有人为此做过。 没有什么特别不寻常的原因 我们还有很多其他事情要做,预算有限,而且这个事情从来没有超过“这不会好吗? 语言设计团队的讨论。 CLR不支持它,因此为了使其工作,除了语言工作之外,我们还需要执行运行时工作。 (见答案评论) 我可以看到有一些体面的用例,但是没有一个是非常有吸引力的,我们会做这个工作,而不是更多次被请求的数百个其他功能之一,或者更有吸引力和更
...
使用Postgres 系统目录获取检查约束列表(对于以下示例中的public模式中的所有表): create table example (id int, val int check (val > 100), str text check (str <> ''));
select nspname schema_name, relname table_name, conname con_name, consrc con_source
from pg_constraint t
join pg_cla
...
你为什么一开始使用泛型? 只需使用方法重载: public static int Sum(A template, int input) { ... }
public static int Sum(B template, int input) { ... }
为避免重复代码,只需委托实现: public static int Sum(A template, int input) { return add(A.Prop, input); }
public static int Sum(B temp
...
通用接口的一个例子是IEnumerable<T> 。 它代表你可以枚举的一些集合。 集合中的项目类型与接口无关,因此它允许您使用通用参数来指定它。 你可以像这样创建一个类: class Foo<T, E> where T : IEnumerable<E>
{ }
这样,通用参数T只能是类型E的集合。约束接口也是通用的。 你也可以这样做: class Foo<T> where T : IEnumerable<string>
{ }
在这种情况下,您不允许任何类型的集合,只允许字符串集合。 你可以
...
它看起来像编译器这样做是因为验证者的一些问题。 您希望编译器生成的IL不可验证,因此C#编译器无法生成它(所有C#代码在“不安全”上下文之外都应该是可验证的)。 “验证类型兼容性”的规则在Ecma规范的第III部分第1.8.1.2.3节中给出。 他们说,使用以下规则,类型'S'与'T'类型或(S:= T)验证兼容: [:=反射]对于所有验证类型S,S:= S [:=是传递性的]对于所有验证类型S,T和U,如果S:= T且T:= U,则S:= U. S:= T如果S是T的基类,或者T和T实现的接口不
...
我怎样才能做到这一点? 你不能。 创建一个专门的Foo 。 class SpecialFoo<T> : Foo<T> where T: SpecificDerivedType
{
void SpecialMethod()
{
//...code...
}
}
其他人提出了一种扩展方法 ,这显然与你所要求的不一样。 这可能是一种解决方法。 How can I achieve this? You can't. Create a specialized Foo.
...
关键是U可以是T一个子类的任何类型,并且您返回的堆栈是该类型的堆栈,而不是T的堆栈。 因此,添加到它的物品必须是U型物品,并且如果物品不为空,则从其返回的物品保证为U 所有熟悉的编译时类型检查的悲欢离合。 Stack<T>可以是T类型或T任何子类别。 该方法的名称表明它返回的堆栈只包含父堆栈中实际属于某个特定子类的项目。 一旦你保证新堆栈中的所有项目都是更专用的类型,那么它更有用,如果这也是新堆栈的类型。 这是一个疯狂的例子(显然,这个“堆栈”类实际上并没有做任何堆栈的事情,但是对于我们的例子来说
...
泛型类型参数的名称可以通过任何有效的标识符名称。 在大多数文档中,您确实可以在TWidget找到T 来自MSDN: 使用描述性名称命名泛型类型参数,除非单个字母名称完全是自解释的,并且描述性名称不会添加值。 The name of the generic type parameter can by any valid identifier name. In most documentation you would indeed find T where you put TWidget. From
...