这个参数类型约束是什么意思?
我正在查看一些代码,我不明白特定约束在以下类定义中的含义:
internal abstract class Entity : Entity where T : Entity { ... }
我不明白这对于参数类型T
。
这类似于“ 奇怪的重复模板模式 ”(但它不一样)。
它可以用于(除其他外)以帮助将派生类中的方法的参数类型约束为与派生类本身相同的类型。
这是Eric Lippert关于这个主题的一篇有趣的博客文章 。
这个的主要用途是强制从Entity
派生的类实现一些接受与派生类相同类型的参数的方法。
在下面的代码示例中,我们在Entity
类中声明了一个方法DoSomethingWithTheSameTypeAsMe()
,它接受类型为T
的参数。
由于generics约束,这将强制从Entity
派生的任何类实现DoSomethingWithTheSameTypeAsMe()
的版本,该版本采用派生类类型的参数。
这是有限的使用,阅读非常混乱,所以我同意Eric Lippert,他说你应该避免这样的代码!
using System; namespace ConsoleApplication1 { internal class Program { private static void Main() { var test1 = new Derived1(); var test2 = new Derived2(); test1.DoSomethingWithTheSameTypeAsMe(test1); test2.DoSomethingWithTheSameTypeAsMe(test2); } } public class Entity { public string Hello() { return "Hello, World."; } } public abstract class Entity: Entity where T: Entity { public abstract void DoSomethingWithTheSameTypeAsMe(T item); } public sealed class Derived1: Entity { // You are forced to implement DoSomethingWithTheSameTypeAsMe() with a param type "Derived1". // (ie the parameter is the same type as 'this') public override void DoSomethingWithTheSameTypeAsMe(Derived1 item) { Console.WriteLine("Doing something with a Derived1 item: " + item.Hello()); } } public sealed class Derived2: Entity { public override void DoSomethingWithTheSameTypeAsMe(Derived2 item) { Console.WriteLine("Doing something with a Derived2 item: " + item.Hello()); } } }
虽然我评论过,但我要坚持我的桨,因为我还要注意基本类型从中得到什么。
简单地说: T
必须inheritanceEntity
。
它是一种经常使用的自引用generics,使得基类可以在方法和其他区域中包含派生类类型 (通过T
)。 它只是避免您必须在派生类型中转换内容或使用基本引用。 虽然我很少在代码中看到它,但它非常有用。
我会注意到这并不意味着基类可以突然访问派生成员。 它仍然只能看到约束定义的最低已知类型(如果存在)。 如果不存在约束,则object
是已知最低的类型。 好处是从派生类型的角度以及它对推入基类的代码授予的清洁度。
在您的情况下,它将看到Entity
和Entity
成员。 这就是限制的原因。
标准用法如下:
public class Customer : Entity { } public abstract class Entity where T : Entity { public T Clone(T entityToClone) { return default(T); // Clone code here, returns derived type. } } // Grants you... Customer clonedCustomer = currentCustomer.Clone(); // Instead of... Customer clonedCustomer = (Customer)currentCustomer.Clone(); // Ignore ethical constraints on cloning customers and definitely do not tell your sales team that you can ;-)
它表示T必须是Entity
类型或从该类型派生
虽然看似矛盾,但它有效并且有时候也很有用,尽管案例很少见,而且往往可以用不同的方式处理。
它在C ++术语中经常被称为奇怪的重复模板模式
在C#中,function比在C ++中使用模式时更受限制。此模式的具体类通常如下所示
class MyClass : Entity> { //... }
或简单地说
class MyClass : Entity { //... }
这可能有用的一个例子是在处理类型的属性时。
假设您在运行时创建小部件列表。 该列表包括从Entity
派生的所有类型,您可以根据属性中的元数据填充信息。 在Entity
您可以一劳永逸地处理这个问题
void RegisterWidget(){ var attributes = typeof(T).GetAttributes(); //do what ever you need to }
这当然可以解决约束但从function角度来看仍然有意义或者显示意图,并且在代码的其他部分可能需要它
它说T
必须是或inheritance自Entity
,这就是你要限制的T
显然T
不能是Entity
因为它是抽象的,所以它必须是从它inheritance的东西。