Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.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#_Generics_Type Parameter_Generic Constraints - Fatal编程技术网

C# 指定类本身的泛型类上的基类约束

C# 指定类本身的泛型类上的基类约束,c#,generics,type-parameter,generic-constraints,C#,Generics,Type Parameter,Generic Constraints,昨天,我向朋友们解释了C#的一般约束。在演示where T:CLASSNAME约束时,我突然想到了如下内容: public class UnusableClass<T> where T : UnusableClass<T> { public static int method(T input){ return 0; } } public class BinaryTree:TreeNode<BinaryTree> { } 公共

昨天,我向朋友们解释了C#的一般约束。在演示
where T:CLASSNAME
约束时,我突然想到了如下内容:

public class UnusableClass<T> where T : UnusableClass<T>
{
    public static int method(T input){
        return 0;
    }
}
public class BinaryTree:TreeNode<BinaryTree>
{
}
公共类UnusableClass,其中T:UnusableClass
{
公共静态int方法(T输入){
返回0;
}
}
看到它被编译,我真的很惊讶。然而,经过一番思考,我认为从编译器的角度来看,它是完全合法的-
UnusableClass
与此约束中可以使用的任何其他类一样,都是一个类

然而,这留下了几个问题:这个类如何使用?有可能吗

  • 实例化它
  • 从中继承
  • 调用它的静态方法
    int方法
  • 如果是,怎么做

    如果这些都是可能的,那么
    T
    的类型是什么

    如果这些都是可能的,T的类型是什么

    它们都是可能的,您将决定
    T
    的类型。例如,让我们假设有一个类型继承自
    UnusableClass

    然后
    T
    的类型变为
    Foo
    ,如果您试图调用
    method
    ,则需要传递
    Foo

    的实例

    public class Implementation : UnusableClass<Implementation>
    {
    }
    
    公共类实现:UnusableClass
    {
    }
    
    是完全有效的,因此

    var unusable = new UnusableClass<Implementation>();
    
    var unusable=新的UnusableClass();
    

    UnusableClass.method(新实现());
    
    有效


    因此,是的,它可以通过提供一个继承类型作为类型参数来实例化,并且与调用静态方法类似。例如,它对于树状结构非常有用,在树状结构中,您希望一般指定节点具有的子节点的类型,而节点本身是相同的类型。

    此方法广泛用于树和其他类似图形的结构中。在这里,您要对编译器说,T有一个无法使用的类API。也就是说,您可以按如下方式实现TreeNode:

    public class TreeNode<T>
        where T:TreeNode<T>
    {
        public T This { get { return this as T;} }
    
        public T Parent { get; set; }
    
        public List<T> Childrens { get; set; }
    
        public virtual void AddChild(T child)
        {
            Childrens.Add(child);
            child.Parent = This;
        }
    
        public virtual void SetParent(T parent)
        {
            parent.Childrens.Add(This);
            Parent = parent;
        }
    }
    
    公共类树节点
    其中T:TreeNode
    {
    公共T This{get{将其作为T;}返回
    公共T父{get;set;}
    公共列表子项{get;set;}
    公共虚拟void AddChild(T child)
    {
    儿童。添加(儿童);
    child.Parent=This;
    }
    公共虚拟void SetParent(T parent)
    {
    parent.Childrens.Add(此);
    父母=父母;
    }
    }
    
    然后像这样使用它:

    public class UnusableClass<T> where T : UnusableClass<T>
    {
        public static int method(T input){
            return 0;
        }
    }
    
    public class BinaryTree:TreeNode<BinaryTree>
    {
    }
    
    公共类二进制树:TreeNode
    {
    }
    
    Hmm。。闻起来像是家庭作业。@JamieKeeling:不,不太像。我只是对它是否可能感兴趣=)我的朋友们完全确定它不是,但我有我的疑问…它是递归类型的一个好模式,如树和图。在几乎所有其他情况下,它都会成为一种反模式,使代码复杂化并降低可读性。我记得我以前工作的代码库,在那里到处都使用。它仍然让我不寒而栗。关联:这不就是F-有界多态性吗?
    public class BinaryTree:TreeNode<BinaryTree>
    {
    }