Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#通用自引用声明_C#_Self Reference - Fatal编程技术网

c#通用自引用声明

c#通用自引用声明,c#,self-reference,C#,Self Reference,我一直在阅读Albaharis的“C#5.0简而言之”,我在泛型部分遇到了这个问题,据说这是合法的: class Bar<T> where T : Bar<T> { ... } class-Bar其中T:Bar{…} 这对我来说毫无意义,尽管我已经仔细阅读了整章。我一点也不懂 有人能用一些可以理解的名字解释一下吗,比如: class Person<T> where T : Person<T> { ... } 类Person,其中T:Perso

我一直在阅读Albaharis的“C#5.0简而言之”,我在泛型部分遇到了这个问题,据说这是合法的:

class Bar<T> where T : Bar<T> { ... }
class-Bar其中T:Bar{…}
这对我来说毫无意义,尽管我已经仔细阅读了整章。我一点也不懂

有人能用一些可以理解的名字解释一下吗,比如:

class Person<T> where T : Person<T> { ... }
类Person,其中T:Person{…}

而在实际应用场景中,这种用法是适当且有用的?

这意味着
T
必须继承自
Person

这是在基类中创建特定于类型的方法、属性或参数的典型方法,特定于实际子体

例如:

public abstract class Base<T> where T : Base<T>, new()
{
    public static T Create()
    {
        var instance = new T();
        instance.Configure(42);
        return instance;
    }

    protected abstract void Configure(int value);
}

public class Actual : Base<Actual>
{
    protected override void Configure(int value) { ... }
}

...

 Actual a = Actual.Create(); // Create is defined in Base, but returns Actual
公共抽象类基类,其中T:Base,new()
{
publicstatict-Create()
{
var instance=newt();
实例配置(42);
返回实例;
}
受保护的抽象空配置(int值);
}
公共类实际值:Base
{
受保护的覆盖无效配置(int值){…}
}
...
实际值a=实际值。创建();//Create在Base中定义,但返回实际值

当您使用某些外部库或框架(您不能或不想修改这些库或框架)时,它非常有用。例如,您有来自此库的类
User
,而使用它的开发人员肯定会定义
CustomUser
类,该类是从它继承的(仅用于添加一些自定义字段)。另外,让我们想象一下,
User
类对其他用户有一些引用,例如:creator和deletor(这显然是
CustomUser
类型的实例)。在这种情况下,通用的自引用声明会很有帮助。我们将后代的类型(
CustomUser
)作为参数传递给base(
User
)类,因此在
User
类声明中,我们可以准确地设置creator和deletor的类型(
CustomUser
),这样就不需要强制转换了:

public class User<TCustomUser> where TCustomUser : User<TCustomUser>
{
    public TCustomUser creator {get;set;}
    public TCustomUser deletor {get;set;}

    //not convenient variant, without generic approach
    //public User creator {get;set;}
    //public User deletor {get;set;}     
}

public class CustomUser : User<CustomUser>
{
    //custom fields:
    public string City {get;set;}
    public int Age {get;set;}
}

我可能会迟到一点,但我想分享一个虚幻世界的应用程序场景以获得乐趣:)

//c语言中的自引用列表#

//我们不能使用泛型类型语法:new List当您有一系列类要编写,并且您意识到80%(选择一个数字)的代码本质上是相同的,只是类型不同时,它也很有用

编写泛型允许您捕获基类中的所有重复代码并重用它

上面的特定模式非常重要/必要,因为您希望T成为您试图编写的类

设想一个框架,其中crud对象基于crudBase,所有内容都继承自crudBase。 进一步想象一下,有一个基类可以帮助您查询这些对象(queryBase),crudBase和queryBase类的比例为1:1

使queryBase成为泛型很简单,因为很明显您将如何声明它

public abstract class queryBase<T> where T : crudBase
{
 public list<T> FindMatches(string SearchCriteria){}

  }
公共抽象类查询数据库,其中T:crudBase
{
公共列表FindMatches(字符串搜索条件){}
}
如果没有泛型,这将必须在每个具体类中,因为返回类型会更改。仿制药非常棒

不太明显的是,如何使用crudBase实现相同级别的通用涅盘。 假设子类中已经有70%的锅炉板积垢代码,但还有10%的代码需要逻辑引用类型。
(选择一个数字,百分比数字不重要)

通用解决方案在这里不太明显。在第一种情况下,泛型类使用T引用另一个类。在这种情况下,您希望使用T引用同一类

使用上述模式,您实际上可以实现以下目标:

public class crudBaseGeneric<T> where T : crudBaseGeneric<T>
{
     public <T> CopyMe(){}
  }
公共类crudBaseGeneric,其中T:crudBaseGeneric
{
公共CopyMe(){}
}
在这里,您将把基类重新定义为泛型,您将能够捕获最后的10%


同样,如果没有泛型,我必须在每个具体类中复制粘贴我的CopyMe()函数。

这可能有点帮助,尽管它不是一个重复或问题的解决方案:问题中有一个关于动物和鸭子的例子,如果我没有弄错的话,这被称为“奇怪的重复模板模式”
public class crudBaseGeneric<T> where T : crudBaseGeneric<T>
{
     public <T> CopyMe(){}
  }