Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通用方法:如何使用可用的最专门的方法强制_C#_Generics_Interface_Overloading_Generic Method - Fatal编程技术网

C# 通用方法:如何使用可用的最专门的方法强制

C# 通用方法:如何使用可用的最专门的方法强制,c#,generics,interface,overloading,generic-method,C#,Generics,Interface,Overloading,Generic Method,我在接口IInterface中定义了一个通用方法Use。我试图实现该接口,其中Use方法的具体实现取决于实际类型T,我希望始终调用最专门的方法。但它不起作用: interface IInterface { void Use<T>(T other) where T : IInterface; } interface IChildInterface : IInterface { } class ImplementsIInterface : IInterface

我在接口
IInterface
中定义了一个通用方法
Use
。我试图实现该接口,其中
Use
方法的具体实现取决于实际类型
T
,我希望始终调用最专门的方法。但它不起作用:

    interface IInterface { void Use<T>(T other) where T : IInterface; }
    interface IChildInterface : IInterface { }
    class ImplementsIInterface : IInterface
    {
        public void Use<T>(T other) where T : IInterface
        {
            Debug.WriteLine("ImplementsInterface.Use(IInterface)");
        }
    }
    class ImplementsChildInterface : IChildInterface
    {
        public void Use<T>(IChildInterface other) where T : IInterface
        { // idea: if other is IChildInterface, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
        }

        public void Use<T>(T other) where T : IInterface
        { // idea: if above method is not applicable, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
        }
    }
采用
ichilInterface
参数的方法永远不会被调用,尽管它应该被调用

有什么办法可以让这一切顺利进行吗?还是我的方法根本错误?

请注意,
IInterface
必须只有一个方法定义。我可以随时扩大接口层次结构(从而增加我可以在实现类中提供的实现的数量),但这不应该导致需要在
IInterface
中添加更多的方法定义。否则,将错过使用接口的全部要点(即灵活)


到目前为止,我得到的答案都涉及到投球的需要。这也是我不想做的事情,因为这会使整个设置毫无用处。让我解释一下我试图实现的目标:

让我们想象一下,我们创建了一个
IInterface
的实例(比如:
IInterface foo=new ImplementsChildInterface();
)。它将以某种方式运行,但它将始终以相同的方式运行-无论我们将其视为
i接口
i接口
实现接口
。因为,如果我们对它调用某个方法,编译器(或运行时?我不知道)将检查它的实际类型,并运行在该类型中定义的方法

现在假设我们有两个
i1
i2
IInterface
实例。它们同样是,
IInterface
的具体实现,因此它们有一个具体的行为,不管我们从哪个角度看它们

因此,当我运行
i1.Use(i2)
时,编译器(或运行时?)应该能够找出
i1
i2
的真正含义,并运行相应的方法。像这样:

  • i1
    有哪种类型<代码>实现接口,好的,然后我来看看那里的方法
  • i2
    有哪种类型
    ImplementsIInterface
    ,好的,那么让我们看看是否存在一个方法
    Use(ImplementsIInterface…
    )。没有,但也许有退路
    ImplementsIInterface
    是一个
    IInterface
    ,所以让我们看看是否存在一个方法
    Use(IInterface…
    )。是的,它是存在的,所以我们叫它
    IInterface
    iChilInterface
    均未定义成员
    Use(iChilInterface-other)
    ,但仅定义
    Use(T-other)

    另一侧的类
    ImplementsChildInterface
    有一个方法
    Use(IChildInterface other)
    。当您将
    childInterf
    声明为
    IChildInterface
    类型的引用时,您不能访问该成员,但必须访问接口中定义的成员。因此,您应该强制转换到实际的类,以便访问接受
    iChilInterface
    实例的方法。但即便如此,还是使用了通用实现。因此,您还应该将参数强制转换为
    iChilInterface

    ImplementsChildInterfacechildinterf = new ImplementsChildInterface();
    childinterf.Use(((IChildInterface)new ImplementsChildInterface()); 
    childinterf.Use(new ImplementsIInterface());
    
    void Use<T>(IChildInterface other) where T : IChildInterface;
    
    此外,由于在更专门的方法中不使用泛型类型参数,因此也可以省略它:

    class ImplementsChildInterface : IChildInterface
    {
        public void Use(IChildInterface other)
        { // idea: if other is IChildInterface, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
        }
    
        public void Use<T>(T other) where T : IInterface
        { // idea: if above method is not applicable, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
        }
    }
    
    现在你可以使用

    IChildInterface childinterf = new ImplementsChildInterface();
    childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
    
    ichilInterface childInterface=new implementschilInterface();
    childinterf.Use(新实现childinterface());//输出“实现接口.使用(接口)”
    

    它将打印所需的输出。

    childinterf.Use(((iChilInterface)new ImplementsChildInterface());
    强制转换仍然不起作用。您是否也将
    childInterface
    强制转换为实际类?您需要两者。或者,从其声明开始,让它成为该类型:
    ImplementsChildInterface=new ImplementsChildInterface();
    。您使用术语“具体实现”和“专门化”就好像C语言泛型就像C++模板一样,它们不是很好。我不是说这是迂腐的,而是指出这些语言是如何达到超载分辨率的根本区别,如果你反对模型,你将遇到一段不愉快的时间。如果你想可靠地调用最具体的方法,请考虑VIR。实际方法,而不是泛型方法。@Jeroenmoster所说的“思考虚拟方法,而不是泛型方法”你的意思是完全不考虑接口吗?因为我考虑过更改
    iChilInterface
    如下:
    interface iIchilInterface:IInterface{重写void Use(T other),其中T:iChilInterface;}
    ,但这种重写似乎是不可能的。至少在类中是可能的。我真的很感激你的提示,因为它清楚地表明我的方法是注定要失败的。但我想不出一个在C#中工作的替代对象模型。“哪种类型……有?”如果您想在运行时解决这些问题,您需要虚拟方法或反射(
    )。泛型将不会帮助您,因为它们只查看它们所使用的上下文的编译时类型。
    ImplementsChildInterface.Use(IChildInterface other)
    永远不能通过
    iChilInterface
    调用,因为
    iChilInterface
    没有该方法。您可以随意命名它,但由于签名不匹配,它不能作为接口的实现。只能
    使用(而不是其他)
    can。为什么你的类中甚至有两个方法?为什么不使用一个接口和一个方法呢?你可以让
    use(T other)
    执行运行时类型检查,或者使用双重分派,并给
    T
    一个你调用的虚拟方法(但这假设
    IChildInterface childinterf = new ImplementsChildInterface();
    childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"