C# 泛型类派生约束的首选语法是什么?

C# 泛型类派生约束的首选语法是什么?,c#,.net,generics,C#,.net,Generics,文档化的派生约束使用了一个where T:子句,我正在修补的示例代码是 public class TwoThingsIPC<T> where T : IPassClass { ... } public class TwoThingsIPC其中T:IPassClass { ... } 其中IPassClass是一个接口 我使用的第三方代码的格式如下 public class TwoThingsIPC<IPassClass> { ... } public class T

文档化的派生约束使用了一个
where T:
子句,我正在修补的示例代码是

public class TwoThingsIPC<T> where T : IPassClass
{ ...
}
public class TwoThingsIPC其中T:IPassClass
{ ...
}
其中IPassClass是一个接口

我使用的第三方代码的格式如下

public class TwoThingsIPC<IPassClass>
{ ...
}
public class TwoThingsIPC
{ ...
}

这两种方法在我的代码中都会导致相同的行为,但它们是否相同?如果不是,区别是什么?

在泛型类型定义中,where子句用于指定类型上的约束,这些约束可以用作泛型声明中定义的类型参数的参数

除了接口约束外,where子句还可以包含基类约束,该约束规定类型必须具有指定的类作为基类(或是该类本身),才能用作该泛型类型的类型参数

如果要检查泛型列表中的项以确定其是否有效,或将其与其他项进行比较,则编译器必须保证它必须调用的运算符或方法将由客户端代码指定的任何类型参数支持。通过对泛型类定义应用一个或多个约束可以获得此保证

参考文献:


where是泛型类型约束

取自


在泛型类型定义中,where子句用于指定 可以用作类型参数的类型上的约束 在泛型声明中定义的参数。例如,你可以 声明泛型类MyGenericClass,这样类型参数 T实现IComparable接口:

以下是一些例子:

public class TwoThingsIPC<T> where T : IPassClass
{ 
}
public class TestClass
{
}
public class TestClass2 : IPassClass
{
}

var test1 = new TwoThingsIPC<TestClass>(); //this will not compile
var test2 = new TwoThingsIPC<TestClass2>(); //this will compile because it implements IPassClass 
public class TwoThingsIPC<T> where T : class
{
}
public class TestClass
{
}
var test1 = new TwoThingsIPC<int>(); //this will not compile because it is a value type

//these will compile because they are reference types 
var test2 = new TwoThingsIPC<TestClass>(); 
var test3 = new TwoThingsIPC<List<TestClass>>(); 

internal delegate void DWork();
var test4 = new TwoThingsIPC<DWork>(); 
public class TwoThingsIPC其中T:IPassClass
{ 
}
公共类TestClass
{
}
公共类TestClass2:IPASClass
{
}
var test1=new TwoThingsIPC()//这不会编译
var test2=新的TwoThingsIPC()//这将编译,因为它实现了IPassClass
其他例子:

public class TwoThingsIPC<T> where T : IPassClass
{ 
}
public class TestClass
{
}
public class TestClass2 : IPassClass
{
}

var test1 = new TwoThingsIPC<TestClass>(); //this will not compile
var test2 = new TwoThingsIPC<TestClass2>(); //this will compile because it implements IPassClass 
public class TwoThingsIPC<T> where T : class
{
}
public class TestClass
{
}
var test1 = new TwoThingsIPC<int>(); //this will not compile because it is a value type

//these will compile because they are reference types 
var test2 = new TwoThingsIPC<TestClass>(); 
var test3 = new TwoThingsIPC<List<TestClass>>(); 

internal delegate void DWork();
var test4 = new TwoThingsIPC<DWork>(); 
public class TwoThingsIPC其中T:class
{
}
公共类TestClass
{
}
var test1=new TwoThingsIPC()//这将不会编译,因为它是值类型
//这些将被编译,因为它们是引用类型
var test2=新的TwoThingsIPC();
var test3=新的TwoThingsIPC();
内部委托void DWork();
var test4=新的TwoThingsIPC();
参考文献:


它们不一样。第二项声明具有误导性:

public class TwoThingsIPC<IPassClass>
{ ...
}
将类型约束到
IPassClass
接口



1事实并非如此,但我还没有更好的解释。

你的例子是错误的。标识符就是标识符,
T
IPassClass
都只是标识符。名字里有什么?因此:

public class TwoThingsIPC<IPassClass>
public class TwoThingsIPC
实际上与:

public class TwoThingsIPC<T>
public class TwoThingsIPC
除非在第一种情况下,您在那里声明的类型参数使用了一个真正的混淆名称

也许你在想另一种情况,你会发现自己在以下两种情况中做出选择:

public class AnotherClass : TwoThingsIPC<IPassClass>
public类另一类:TwoThingsIPC
以及:

public类另一类:TwoThingsIPC
其中TPass:IPassClass
其中,在这两种情况下,
IPassClass
必须是已在别处声明的类型


请注意,第一个类是非泛型类,它的基类是泛型类。第二个是泛型类(因为
TPass
声明有它的类型参数),它有一个依赖于自己泛型参数的基类。

感谢您的帮助;为了收集相关的回答并确保我掌握的事实是正确的:

Asawyer对原始帖子的评论指出了泛型的约束和参数之间的区别。。。而D Stanly说明了在需要约束的地方使用参数如何导致草率的类型匹配

Jeppe Stig Nielsen发现我很快就会想要编写从泛型类继承的类,并使用接口参数。我问过他在哪里可以找到这样做的例子

所有这些都提供了坚实的支持,可以进行一些依赖注入。。。
再次感谢

第二种形式只是使用一个以I开头的类型参数名称——我不推荐这样做。它不强制任何约束。第一个是,第二个是“我的代码中的相同行为”???您能否将两种通用定义都包含在
TwoThingsIPC
中?(除非没有显示相关代码,否则在第二个版本中您应该可以做得很好)@Alexei--我可以尝试使用string类作为约束和参数,以确定@asawyer推荐的差异。+1基本上,IPassClass的接口名称“隐藏”了IPassClass泛型参数,就像方法中的变量一样包含类中的“隐藏”字段Thank Jeppe您知道我在哪里可以找到使用从泛型继承的带有接口参数的具体类的示例(您知道一个简单的示例)吗?例如
公共类另一个类:TwoThingsIPC