繁体   English   中英

泛型类继承问题

[英]Generic class Inheritance issue

我有以下情况:

class MyControl<T> : UserControl where T:TClass
{
    public T Field {}
    public event EventHandler<MyEventArgs<T>> MyEvent;
}
class DerControl1 : MyControl<ClassA> {}
class DerControl2 : MyControl<ClassB> {}

我应该如何实现继承以使DerControl1具有基类,DerControl2可以访问MyControl的接口?

SomeBaseClass control = condition ? DerControl1 :DerControl2;
control.Field = null;
control.Enabled=false;

SomeBaseClass应该是什么类?

定义另一个非通用接口IMyControl并明确实现它:

public interface IMyControl
{
    public TClass Field { get; set; }
    public bool Enabled { get; set; }
}

class MyControl<T> : UserControl, IMyControl where T:TClass
{
    public T Field { get; set; }
    TClass IMyControl.Field
    {
        get { return this.Field; }
        set { this.Field = (T)value; }
    }
    public event EventHandler<MyEventArgs<T>> MyEvent;
}

您现在可以将派生控件转换为IMyControl ,并将Field属性作为类型TClass 试图返回其他任何违反co / contravariance的东西(你可以返回一个object但在这种情况下最好返回一个TClass因为类型约束已经存在)

您可以使用UserControl访问Enabled字段,但没有定义Field常用类型。 您不能将Field放在一个通用的非泛型接口中,因为它的类型是通用的。

从C#4.0开始,您可以使用dynamic类似的东西:

dynamic control = condition ? DerControl1 :DerControl2;
control.Field = null;
control.Enabled=false;

这可能会稍慢,但它会编译并执行您想要的操作。

用例不清楚。 如果这段代码:

control.Field = null;
control.Enabled=false;

将不会放入泛型方法(或泛型方法),而不是根本不需要泛型:

class MyControl : UserControl where T:TClass
{
    public object Field {}
    public event EventHandler<MyEventArgs> MyEvent;
}

否则,此代码将正常工作。

使用您自己的问题,您不能只使用一个界面吗?

public interface IMyControl<T> where T:class
{
    T Field { get; set;}
    event EventHandler<MyEventArgs<T>> MyEvent;
}

public class MyControl<T> : UserControl, IMyControl<T> where T:class
{
    public T Field { get; set;}
    public event EventHandler<MyEventArgs<T>> MyEvent;       
}

然后使用:

// (which equates to IMyControl control = ...)
var control = condition ? new MyControl<ClassA>() : new MyControl<ClassB>();
control.Field = null;
control.Enabled = false;

这样可以节省您希望使用的每个Type参数的多个类,从而鼓励代码重用并遵循多态(OOP)。

希望有所帮助!

编辑

好的 - 所以亚历克斯是对的,我不应该对那个人开火! 经过一番调查后,这似乎比我想象的要困难得多! 所以我开始怀疑你所问的是不是正确的方法。 现在,无论是否是你想要的那种答案,我都不知道,但这里是你思考的问题。

基本上,不要使用泛型。 在这种情况下,它会让生活变得非常困难! 相反,隐藏在接口后面。 下面的代码实现了与您上面尝试的相同,但除了您现在将字段绑定到“具体”接口。 但实际上,你想要这个 - 你应该知道已知的行为和模式,否则,在我看来,你不知道你的系统应该做什么,因此你的要求有问题。 不管怎么说,这里有一些代码!

public interface IMyClass
{
    int I { get; set; }
    string S { get; set; }
}

public interface IMyControl
{
    IMyClass Field { get; set; }
    event EventHandler<EventArgs> MyEvent;
}

public class MyControl : UserControl, IMyControl
{
    public MyControl(IMyClass field)
    {
        this.Field = field;
    }

    public IMyClass Field { get; set; }

    public event EventHandler<EventArgs> MyEvent;
}

public class MyClass1 : IMyClass
{
    public int I { get; set; }
    public string S { get; set; }

    public override string ToString()
    {
        return "I am a MyClass1!!!";
    }
}

public class MyClass2 : IMyClass
{
    public int I { get; set; }
    public string S { get; set; }

    public override string ToString()
    {
        return "I am a MyClass2!!!";
    }
}

var control = someCondition ? new MyControl(new MyClass1()) : new MyControl(new MyClass2());

暂无
暂无

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

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