泛型类继承问题

时间:2013-04-17 09:35:56

标签: c# oop generics

我有以下情况:

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应该是什么类?

4 个答案:

答案 0 :(得分:2)

定义另一个非通用接口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,因为类型约束已经存在)

答案 1 :(得分:1)

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

从C#4.0开始,您可以使用dynamic来实现这样的目标:

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

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

答案 2 :(得分:0)

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

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

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

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

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

答案 3 :(得分:0)

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

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());