【问题标题】:keep code organized using generic types使用泛型类型组织代码
【发布时间】:2012-01-15 08:01:26
【问题描述】:

我喜欢在编程时把事情分开。这就是我认为继承很重要的原因之一。

我使用的 dll 文件包含一个我无法修改的类。 dll 文件包含 ClassA 来说明我的示例。

class Program
{
    static void Main(string[] args)
    {
        ClassA object1 = new ClassA();

        SomeMethod<ClassA>(object1 ); // error because " a does not implement ITemp"
    }

    static T SomeMethod<T>(T input)
        where T:ITemp // make sure input has a method MyCustomMethod
    {

        input.MyCustomMethod();

        return input;
    }
     // create this interface so that compiler does not complain when
     // calling MyCustomMethod in method above

    interface ITemp
    {
        void MyCustomMethod();
    }

}


// classA is a sealed class in a dll file that I cannot modify
public class ClassA
{
    public void MyCustomMethod()
    {

    }
}

如果 object1 确实实现了 ITemp 接口,为什么会出现错误! object1 有方法 MyCustomMethod()

我知道我可以使用反射来解决这个问题,但我喜欢保持我的代码干净。我也想避免使用动态类型。

【问题讨论】:

    标签: c# generics reflection dynamic


    【解决方案1】:

    ClassA 没有实现 ITemp 接口。仅仅因为它有一个与 ITemp 接口中的方法具有相同名称和签名的方法并不意味着它实现了该接口。需要声明该类以显式实现它。

    既然你不能扩展 ClassA,我能想到的最好的办法就是用一个适配器类型类来包装它:

    public ClassB : ITemp {
        protected ClassA classAInstance;
    
        public ClassB( ClassA obj ) {
            classAInstance = obj;
        }
    
        public void MyCustomMethod() {
            classAInstance.MyCustomMethod();
        }
    }
    

    然后在你的 main 方法中:

    static void Main(string[] args)
    {
        ClassA object1 = new ClassA();
    
        SomeMethod<ClassB>(new ClassB(object1));
    }
    

    【讨论】:

    • 非常感谢!这是一件好事。 MyCustomMethod 不是静态的,因此我必须在类 b 中实例化 classAInstance,因此我必须在类 B 中创建适当的构造函数。我想这次我将不得不使用反射。我只打算使用 3 种方法...
    • 一个小修正:需要声明类或其在继承链中的一个祖先类才能显式实现它。另外,以免有人混淆,这里的“显式”一词与接口成员的隐式与显式实现的概念无关。
    【解决方案2】:

    您正在尝试使用duck typing。 C# 通常不支持 dynamic 类型之外的内容。 ClassA 将需要实现接口,正如您所指出的那样,它不会也不能实现。您可以使用代理包装类,但这可能不是一个好主意。

    【讨论】:

    • C# 在其他一些地方确实支持鸭子类型,尤其是 foreach 循环。
    • @phoog 你是对的。每天学习新东西reference
    • 引用也有错误。它说Current 属性必须返回一个对象,但实际上Current 属性可以返回任何东西。这就是语言设计者选择指定这种鸭子类型的原因:因此,在泛型之前的世界中,我们可以为值类型编写自定义枚举器,其Current 属性可以返回未装箱的值类型,避免大量装箱和拆箱开销。
    猜你喜欢
    • 2011-01-13
    • 2021-10-22
    • 2011-12-25
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多