通用方法无法推断类型

时间:2019-11-18 13:16:07

标签: c# generics

我很难理解c#编译器为何无法编译以下示例:

    interface ISetUp
    {
        void SetUp<T>(T parameter);
    }

    class DeviceParameter 
    {
        public string Param { get; set; }
    }

    // implementation of ISetUp
    class Device : ISetUp
    {
        // Generates a warning here: 'Type parameter DeviceParameter hides class DeviceParameter'
        public void SetUp<DeviceParameter>(DeviceParameter parameter)
        {
            /* Terrible error here: 
            * 'DeviceParameter' does not contain a definition for 'Param' and no 
            * accessible extension method 'Param' accepting a first argument of type 
            * 'DeviceParameter' could be found (are you missing a using directive 
            * or an assembly reference?)  
            */
            Console.WriteLine(parameter.Param);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var device = new Device();
            device.SetUp(new DeviceParameter { Param = "Com1"});
        }
    }

我不明白为什么编译器对我的接口实现不满意。如果我将参数存储在类变量中,那就更不高兴了:

    class Device : ISetUp
    {
        private DeviceParameter param;
        public void SetUp<DeviceParameter>(DeviceParameter parameter)
        {
            // Error here: Cannot implicitly convert type 'DeviceParameter' to 'ConsoleApp.DeviceParameter'
            param = parameter;
        }
    }

当我在界面中将方法类型更改为类类型时,我可以很高兴地使用我的参数:

    interface ISetUp<T>
    {
        void SetUp(T parameter);
    }

我完全确定这是一个重复的问题,但是我找不到合适答案的链接。我只是想不理解泛型方法的概念。如果有人会为我指出正确的方向,我真的很感激。

5 个答案:

答案 0 :(得分:3)

当您执行public void SetUp<DeviceParameter>(DeviceParameter parameter)时,实际上定义了带有通用参数SetUp的通用方法DeviceParameter。此类型与您的课程无关。 因此,您只需要用第二个代码即可实现:

    interface ISetUp<T>
    {
        void SetUp(T parameter);
    }

如果您还有其他问题,我们很乐意为您解答:-)

答案 1 :(得分:1)

您将方法定义为通用方法,因此必须将其实现为通用方法。您可以将通用属性添加到Type而不是方法中:

interface ISetUp<T>
{
    void SetUp(T parameter);
}

与实现此接口时相比,您可以指定通用属性:

class Device : ISetUp<DeviceParameter>
{
    public void SetUp(DeviceParameter parameter)
    {
        Console.WriteLine(parameter.Param);
    }
}

答案 2 :(得分:0)

SetUp<T>(T parameter)表示让呼叫者决定他要使用什么参数。从理论上讲,我可以称呼mySetupClass.SetUp<string>("")mySetupClass.SetUp<int>(3)

通过用SetUp<DeviceParameter>覆盖它,您确实隐藏了原始方法。

也许您想做的就是使您的界面通用,例如:ISetUp<T>

答案 3 :(得分:0)

 SetUp<DeviceParameter>(DeviceParameter parameter)

看起来像是对您的DeviceDevice类的引用,但并非如此。 这完全等同于

 SetUp<T>(T parameter)

我希望这可以解释为什么不知道T.Param或DeviceParameter.Param。

您应该拥有

class Device : ISetup<DeviceParameter>

public void SetUp(DeviceParameter parameter)

答案 4 :(得分:0)

我通过此实现更改了下面的代码,它可以正常工作。

  

通用类型参数允许您在编译时为方法指定任意类型T,而无需在方法或类声明中指定具体类型。

    public class Device : ISetUp
    {
        // Generates a warning here: 'Type parameter DeviceParameter hides class DeviceParameter'

        public void SetUp<T>(T parameter)
        {
            DeviceParameter dd = parameter as DeviceParameter;
            Console.WriteLine(dd.Param);

        }
    }