我在看一些代码,我不明白什么是特定的约束在下面的类定义是指:这个参数类型约束是什么意思?
internal abstract class Entity<T> : Entity
where T : Entity<T>
{ ... }
我不明白,这意味着有关参数类型T
。
我在看一些代码,我不明白什么是特定的约束在下面的类定义是指:这个参数类型约束是什么意思?
internal abstract class Entity<T> : Entity
where T : Entity<T>
{ ... }
我不明白,这意味着有关参数类型T
。
这与“Curiously Recurring Template Pattern”类似(但它不相同)。
它可以用来(除其他外)帮助将派生类中的方法的参数类型约束为与派生类本身相同的类型。
Here's an interesting blog post from Eric Lippert on this subject。
此主要用于强制从Entity<T>
派生的类实现某种方法,该方法接受与派生类相同类型的参数。
在下面的代码示例中,我们在Entity<T>
类中声明了一个方法DoSomethingWithTheSameTypeAsMe()
,它接受T
类型的参数。
由于通用约束,这将强制从Entity<T>
派生的任何类实现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<T>: Entity where T: Entity<T>
{
public abstract void DoSomethingWithTheSameTypeAsMe(T item);
}
public sealed class Derived1: Entity<Derived1>
{
// You are forced to implement DoSomethingWithTheSameTypeAsMe() with a param type "Derived1".
// (i.e. 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<Derived2>
{
public override void DoSomethingWithTheSameTypeAsMe(Derived2 item)
{
Console.WriteLine("Doing something with a Derived2 item: " + item.Hello());
}
}
}
它说,T
必须或Entity<T>
,这就是有,你限制T
继承。显然T
不能是Entity<T>
因为这是抽象的,所以它必须是从它继承的东西。
它说,T必须Entity<T>
类型或从该类型
派生虽然它似乎是自相矛盾它是有效的,有时是太有用,虽然情况是罕见的,往往可以在不同的处理更容易undertand方法。
它经常refered在C++行话为Curiously recurring template pattern
在C#中的功能有些在C++中的具体类此图案的使用模式时相比,更多的限制通常会这个样子
class MyClass<ItemType> : Entity<MyClass<ItemType>> {
//...
}
或简单地
时这可能是有用的class MyClass : Entity<MyClass> {
//...
}
一个实例是具有在所述类型的属性工作时。
假设您在运行时创建小部件列表。该列表包含从Entity<T>
派生的所有类型,并根据来自属性的元数据填充信息。在Entity<T>
可以处理这个一劳永逸
void RegisterWidget(){
var attributes = typeof(T).GetAttributes();
//do what ever you need to
}
这当然与出约束的工作,但它仍然可能从功能角度看是有意义还是表现出打算,并可能在其他部分需要代码
为什么是DW?这个答案中没有任何不正确的,它回答了这个问题 – 2013-04-22 08:39:20
虽然我评论过,我会坚持我的桨,因为我也想说明基础类型从中得到什么。
只需:T
必须继承Entity<T>
。
这是一种自引用泛型,通常用于在基类中包含派生类类型(通过T
)在方法和其他领域。它只是避免你必须投入东西或在派生类型中使用基础引用。虽然我很少看到它用在我们的代码中,但它可能非常有用。
我会注意到这是的不是表示基类可以突然访问派生成员。它仍然只能看到由约束定义的最低已知类型(如果它们存在)。如果不存在约束条件,object
是已知类型最低的。好处是从派生类型的角度以及它被赋予基类的代码的清洁度。
在你的情况下,它会看到Entity<T>
和Entity
成员。这是约束的原因。
标准用法是这样的:
public class Customer : Entity<Customer>
{
}
public abstract class Entity<T>
where T : Entity<T>
{
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 ;-)
我很抱歉,但你不混淆C++模板与C#泛型? – 2013-04-22 08:38:37
C#的原理不一样吗?重要的是这种类型受到这种限制。 – 2013-04-22 08:40:12
我同意,这个答案是不正确的。在CRTP中,基类也是通用的,这里不是这种情况。如果你在这里说'Base''与'Entity '相同,你也是不正确的,因为在C#中你不能以这种方式访问派生类的成员。 –
2013-04-22 08:40:16