繁体   English   中英

这个参数类型约束是什么意思?

[英]What does this parameter type constraint mean?

我正在查看一些代码,我不明白特定约束在以下类定义中的含义:

internal abstract class Entity<T> : Entity
    where T : Entity<T>
{ ... }

我不明白这对参数类型T

这类似于“ 奇怪的重复模板模式 ”(但它不一样)。

它可以用于(除其他外)以帮助将派生类中的方法的参数类型约束为与派生类本身相同的类型。

这是Eric Lippert关于这个主题的一篇有趣的博客文章

这个的主要用途是强制从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 )。 它简单地避免了您必须在派生类型中转换内容或使用基本引用。 虽然我很少在代码中看到它,但它非常有用。

我会注意,这并不意味着基类可突然访问派生成员。 它仍然只能看到约束定义的最低已知类型(如果存在)。 如果不存在约束,则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 ;-)

它表示T必须是Entity<T>类型或从该类型派生

尽管看似矛盾,但它有效并且有时候也很有用,尽管案例很少见,而且往往可以用不同的方式处理。

它在C ++术语中经常被称为奇怪的重复模板模式

在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
}

这当然可以解决约束但从功能角度来看仍然有意义或者显示意图,并且可能在代码的其他部分需要它

它说T必须是或继承自Entity<T> ,这就是你所限制的T 显然T不能是Entity<T>因为它是抽象的,所以它必须是从它继承的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM