【问题标题】:C# Generic Inheritance workaroundC# 泛型继承解决方法
【发布时间】:2011-05-22 20:03:28
【问题描述】:

例子:

我想要几个从 TextBox 或 RichTextBox 派生的专用文本框,它们都派生自 TextBoxBase:

class CommonFeatures<T> : T where T : TextBoxBase
{
  // lots of features common to the TextBox and RichTextBox cases, like
    protected override void OnTextChanged(TextChangedEventArgs e) 
    { 
        //using TextBoxBase properties/methods like SelectAll();  
    }
}

然后

class SpecializedTB : CommonFeatures<TextBox>
{
    // using properties/methods specific to TextBox
    protected override void OnTextChanged(TextChangedEventArgs e) 
    { 
        ... base.OnTextChanged(e); 
    }
}

class SpecializedRTB : CommonFeatures<RichTextBox>
{
    // using methods/properties specific to RichTextBox
}

很遗憾

class CommonFeatures<T> : T where T : TextBoxBase

无法编译(“不能从 'T' 派生,因为它是类型参数”)。

有没有好的解决方案?谢谢。

【问题讨论】:

  • 应该是类 CommonFeatures where T : TextBoxBase
  • @Tomas Voracek 这就是重点,类 CommonFeatures : T where T : TextBoxBase 因为 CommonFeatures 需要从继承 TextBoxBase 的方法/属性的类派生,否则 OnTextChanged 之类的东西不存在。如果我直接从TextBoxBase继承,我以后如何添加来自RichTextBox或TextBox的属性/方法,没有多重继承......

标签: c# generics inheritance


【解决方案1】:

C# 泛型不支持从参数类型继承。

你真的需要 CommonFeatures 派生自 TextBoxBase 吗?

一个简单的解决方法可能是使用聚合而不是继承。这样你就会有这样的东西:

public class CommonFeatures<T> where T : TextBoxBase
{
    private T innerTextBox;

    protected CommonFeatures<T>(T inner)
    {
        innerTextBox = inner;
        innerTextBox.TextChanged += OnTextChanged;
    }

    public T InnerTextBox { get { return innerTextBox; } }

    protected virtual void OnTextChanged(object sender, TextChangedEventArgs e) 
    { 
        ... do your stuff            
    }
}

就像@oxilumin 所说,如果您真的不需要CommonFeatures 成为TextBoxBase,扩展方法也可能是一个很好的选择。

【讨论】:

  • 谢谢,我想我会这样做,我想你的意思是: class SpecializedRTB : RichTextBox { private CommonFeatures cf = new CommonFeatures(this); // SpecializedRTB 的 TextChanged 事件已经被捕获。我怎么没想到:)
【解决方案2】:

如果您的 CommonFeature 类没有它自己的条件 - 您可以为此使用扩展方法。

public static class TextBoxBaseExtensions
{
    public static YourReturnType YourExtensionMethodName(this TextBoxBase textBoxBase, /*your parameters list*/)
    {
        // Method body.
    }
}

然后你可以以同样的方式使用这个方法来处理所有真正的类方法:

var textBox = new TextBox();
textBox.YourExtensionMethodName(/* your parameters list */);

【讨论】:

  • 谢谢,我会调查一下,但这是否允许受保护的覆盖机制?我必须添加受保护的覆盖 void OnTextChanged(TextChangedEventArgs e) { ... base.ExtensionOnTextChanged(e); } 在这两个课程中手动?
  • @SemMike:不,使用扩展方法你只能访问类的公共成员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多