ChristianMurschall
ChristianMurschall

Reputation: 1711

Generic method cannot infer type

I'm having trouble to understand why the c# compiler is in trouble compiling the following example:

    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"});
        }
    }

I cannot understand why the compiler is unhappy with my implementation of the interface. If I was to store the parameter in a class variable, it's even more unhappy:

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

When I change in my interface the method type to a class type I can cheerful use my parameter:

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

I'm totally sure this is a duplicate question, but I fail to find a link to an appropriate answer. I just seam to not understand the concept of generic methods. If someone would be kind to point me into the right direction, I really appreciate it.

Upvotes: 1

Views: 156

Answers (5)

Pablo notPicasso
Pablo notPicasso

Reputation: 3161

You define method as generic so you must implement it as generic. You could add generic attribute to Type instead of method:

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

than when you implement this interface you specify generic attribuite:

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

Upvotes: 1

Holger
Holger

Reputation: 2652

This

 SetUp<DeviceParameter>(DeviceParameter parameter)

Looks like a reference to your class DeviceParameter, but it isn't. This is completly equivalent to

 SetUp<T>(T parameter)

I hope this explains, why T.Param or DeviceParameter.Param is not known..

You should have

class Device : ISetup<DeviceParameter>

and

public void SetUp(DeviceParameter parameter)

Upvotes: 0

Jayakumar Thangavel
Jayakumar Thangavel

Reputation: 2005

I changed the below part of code with this implementation, it works.

A generic type parameter allows you to specify an arbitrary type T to a method at compile-time, without specifying a concrete type in the method or class declaration.

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

        }
    }

Upvotes: 0

Lukasz Nowakowski
Lukasz Nowakowski

Reputation: 336

When you do public void SetUp<DeviceParameter>(DeviceParameter parameter) you actually define a generic method SetUp with generic parameter DeviceParameter. This type has nothing to do with your class. So what you want, you can only achieve with your second code:

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

If you have more questions, I'll be happy to answer them :-)

Upvotes: 3

Guillaume Pansier
Guillaume Pansier

Reputation: 201

SetUp<T>(T parameter) means you let the caller decide what parameter he wants to use. I could theoretically call both mySetupClass.SetUp<string>("") and mySetupClass.SetUp<int>(3)

By overriding it with SetUp<DeviceParameter> you are indeed hiding the original method.

Maybe what you wanted to do is make your interface generic, like: ISetUp<T>

Upvotes: 0

Related Questions