C# 泛型类的泛型父类

C# 泛型类的泛型父类,c#,generics,C#,Generics,我用一个虚构的例子来说明这一点。比如说,我有一个小部件类,比如: abstract class Widget { Widget parent; } 现在,我的其他类将从这个Widget类派生,但是假设我想在定义派生类型时在类中添加一些约束,这样只有特定“类型”的Widget可以是特定类型的Widget的父类 例如,我从Widget类派生了另外两个Widget,WidgetParent和WidgetChild。在定义子类时,我想将父类的类型定义为WidgetParent,这样我就不必每次使用它时

我用一个虚构的例子来说明这一点。比如说,我有一个小部件类,比如:

abstract class Widget
{
Widget parent;
}
现在,我的其他类将从这个Widget类派生,但是假设我想在定义派生类型时在类中添加一些约束,这样只有特定“类型”的Widget可以是特定类型的Widget的父类

例如,我从Widget类派生了另外两个Widget,WidgetParent和WidgetChild。在定义子类时,我想将父类的类型定义为WidgetParent,这样我就不必每次使用它时都对父类进行类型转换

确切地说,我想做的是:

// This does not works!
class Widget<PType>: where PType: Widget
{
    PType parent;
}

class WidgetParent<Widget>
{
    public void Slap();
}

class WidgetChild<WidgetParent>
{
}
我想这样使用它(如果我可以使用泛型):


我认为没有一种语言机制允许你这么做

但是,您可能希望使用将类的构造与类本身分开

比如说,创建一个WidgetFactory类

class WidgetFactory
{
    Widget CreateWidget()
    {
        return new Widget();
    }
}
而对于儿童班,你也可以制作他们的工厂。例如,WidgetParentFactory或WidgetChildFactory,或者您可以创建一个通用工厂:

class WidgetFactory<T> where T : Widget
{
    T CreateWidget()
    {
        return new T();
    }
}
类WidgetFactory,其中T:Widget
{
T CreateWidget()
{
返回新的T();
}
}
然后,通过CreateWidget()方法可以控制类实例化,从而无法创建无效的子类型

class WidgetFactory<T> where T : Widget
{
    T CreateWidget()
    {
        if (/*check the type T inheritance here*/)
            return new T();
        else
            throw new Exception("Invalid inheritance");
    }
}
类WidgetFactory,其中T:Widget
{
T CreateWidget()
{
如果(/*请在此处检查类型T继承*/)
返回新的T();
其他的
抛出新异常(“无效继承”);
}
}
这应该对你有好处


p、 您是否愿意详细说明您为什么要这样做?

您应该能够通过仍然使用非通用类
小部件
并使
小部件
从中派生出来来使用您得到的代码:

public abstract class Widget
{
}

public abstract class Widget<T> : Widget where T : Widget
{
}
公共抽象类小部件
{
}
公共抽象类Widget:Widget,其中T:Widget
{
}

然后,您需要确定哪些属于泛型类,哪些属于非泛型类。。。根据经验,这可能是一个棘手的平衡行为。希望能有相当数量的来回

您似乎混淆了类型参数和继承。这应该起作用:

class Widget<PType> where PType :new()
{
    public  PType parent = new PType();
}

class ParentType {}

class WidgetParent : Widget<ParentType> 
{    
    public void Slap() {Console.WriteLine("Slap"); }
}

class WidgetChild : Widget<WidgetParent>
{
}
public static void RunSnippet()
{
    WidgetChild wc = new WidgetChild();
    wc.parent.Slap();
}
类小部件,其中PType:new()
{
public PType parent=new PType();
}
类父类型{}
WidgetParent类:小部件
{    
public void Slap(){Console.WriteLine(“Slap”);}
}
WidgetChild类:小部件
{
}
公共静态void RunSnippet()
{
WidgetChild wc=新的WidgetChild();
wc.parent.Slap();
}
使用接口:

interface IContainerWidget { }

class Widget
{
    private IContainerWidget Container;
}

class ContainerWidget : Widget, IContainerWidget
{
}

这是我组织这件事的方法

public interface IWidget
{
    void Behave();
    IWidget Parent { get; }
}

public class AWidget : IWidget
{
    IWidget IWidget.Parent { get { return this.Parent; } }
    void IWidget.Behave() { this.Slap(); }

    public BWidget Parent { get; set; }
    public void Slap() { Console.WriteLine("AWidget is slapped!"); }
}

public class BWidget : IWidget
{
    IWidget IWidget.Parent { get { return this.Parent; } }
    void IWidget.Behave() { this.Pay(); }

    public AWidget Parent { get; set; }
    public void Pay() { Console.WriteLine("BWidget is paid!"); }
}

public class WidgetTester
{
    public void AWidgetTestThroughIWidget()
    {
        IWidget myWidget = new AWidget() { Parent = new BWidget() };
        myWidget.Behave();
        myWidget.Parent.Behave();
    }
    public void AWidgetTest()
    {
        AWidget myWidget = new AWidget() { Parent = new BWidget() };
        myWidget.Slap();
        myWidget.Parent.Pay();
    }

    public void BWidgetTestThroughIWidget()
    {
        IWidget myOtherWidget = new BWidget() { Parent = new AWidget() };
        myOtherWidget.Behave();
        myOtherWidget.Parent.Behave();
    }

    public void BWidgetTest()
    {
        BWidget myOtherWidget = new BWidget() { Parent = new AWidget() };
        myOtherWidget.Pay();
        myOtherWidget.Parent.Slap();
    }
}

我有一个类似的问题,并对其进行了调整以适应这一点(希望如此)

主代码

public class Parent<T>
    where T : Child<T>
{
    public Parent() { }


    public T Get()
    {
        return Activator.CreateInstance(typeof(T), new object[] { this }) as T;
    }
}

public class Child<T>
    where T : Child<T>
{
    Parent<T> _parent;

    public Parent<T> Parent { get { return _parent; } }

    public Child(Parent<T> parent)
    {
        _parent = parent;
    }
}


public class ItemCollection : Parent<Item>
{

}

public class Item : Child<Item>
{
    public Item(Parent<Item> parent)
        : base(parent)
    {
    }
}

谢谢你的努力,查克里特。我已经详细阐述了它的用法。我认为重点是将父类型也约束为某种小部件。@Jon:没错,父类型具有上述约束。
public interface IWidget
{
    void Behave();
    IWidget Parent { get; }
}

public class AWidget : IWidget
{
    IWidget IWidget.Parent { get { return this.Parent; } }
    void IWidget.Behave() { this.Slap(); }

    public BWidget Parent { get; set; }
    public void Slap() { Console.WriteLine("AWidget is slapped!"); }
}

public class BWidget : IWidget
{
    IWidget IWidget.Parent { get { return this.Parent; } }
    void IWidget.Behave() { this.Pay(); }

    public AWidget Parent { get; set; }
    public void Pay() { Console.WriteLine("BWidget is paid!"); }
}

public class WidgetTester
{
    public void AWidgetTestThroughIWidget()
    {
        IWidget myWidget = new AWidget() { Parent = new BWidget() };
        myWidget.Behave();
        myWidget.Parent.Behave();
    }
    public void AWidgetTest()
    {
        AWidget myWidget = new AWidget() { Parent = new BWidget() };
        myWidget.Slap();
        myWidget.Parent.Pay();
    }

    public void BWidgetTestThroughIWidget()
    {
        IWidget myOtherWidget = new BWidget() { Parent = new AWidget() };
        myOtherWidget.Behave();
        myOtherWidget.Parent.Behave();
    }

    public void BWidgetTest()
    {
        BWidget myOtherWidget = new BWidget() { Parent = new AWidget() };
        myOtherWidget.Pay();
        myOtherWidget.Parent.Slap();
    }
}
public class Parent<T>
    where T : Child<T>
{
    public Parent() { }


    public T Get()
    {
        return Activator.CreateInstance(typeof(T), new object[] { this }) as T;
    }
}

public class Child<T>
    where T : Child<T>
{
    Parent<T> _parent;

    public Parent<T> Parent { get { return _parent; } }

    public Child(Parent<T> parent)
    {
        _parent = parent;
    }
}


public class ItemCollection : Parent<Item>
{

}

public class Item : Child<Item>
{
    public Item(Parent<Item> parent)
        : base(parent)
    {
    }
}
ItemCollection col = new ItemCollection();
Item item = col.Get();
item.Parent.Slap();