开发者

Generic method with Action<T> parameter

开发者 https://www.devze.com 2022-12-12 04:34 出处:网络
So, I\'m sure this has been answered somewhere out there before, but I couldn\'t find it anywhere. Hoping some generics guru can help.

So, I'm sure this has been answered somewhere out there before, but I couldn't find it anywhere. Hoping some generics guru can help.

public interface IAnimal{}
public class Orangutan:IAnimal{}

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
    Orangutan orangutan = new Orangutan();
    action(orangutan);  //Compile error 1

    //This doesn't work either:
    IAnimal animal = new Orangutan();
    action(animal);  //Compile error 2
}
  1. Argument type 'Orangutan' is not assignable to parameter type 'T'
  2. Argument type 'IAnimal' is not assignable to parameter type 'T'

Edit: Based on Yuriy and other's suggestions, I could do some casting such as:

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
    Orangutan orangutan = new Orangutan();
    action((T)(IAnimal)orangutan);

    //This doesn't work either:
    IAnimal animal = new Orangutan();
    action((T)animal);
}

The thing I wanted to do was call the ValidateUsing method like this:

ValidateUsing(Foo);  

Unfortunately, if foo looks like this:

private void Foo(Orangutan obj)
{
    //Do something
}

I have to explicitly specify t开发者_开发知识库he type when I call ValidateUsing

ValidateUsing<Orangutan>(Foo);


Why are you instantiating an Orangutan if you are supposed to be accepting any IAnimal?

public void ValidateUsing<T>(Action<T> action) where T : IAnimal, new()
{
    T animal = new T();
    action(animal);  //Compile error 2

If you reuse your generic parameter, you won't have any type issues...

Now, with regard to why your code doesn't work, all that you're saying is that the type T will derive from IAnimal. However, it could just as easily be a Giraffe as an Orangutan, so you can't just assign an Orangutan or IAnimal to a parameter of type T.


The thing is, that T represents some type which by the way implements IAnimal.

So, when you try to compile action(new Organatum()) you getting an error because you have declared that the action should take a parameter of type T which in its turn could be of type, let's say, Fish - you can't cast Organatum to a Fish, can you?

If you want to trigger any action which takes parameter of a type which implements IAnimal interface, then simply forget about generics and use Action<IAnimal>.

HTH.


Make the following changes:

Orangutan orangutan = new Orangutan();
action((T)(IAnimal)orangutan); 


IAnimal animal = new Orangutan();
action((T)animal); 


Try this.

Orangutan orangutan = new Orangutan();
Action<IAnimal> castedAction = action as Action<IAnimal>;
castedAction(orangutan);


public interface IAnimal { }
public class Orangutan : IAnimal { }

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
    Orangutan orangutan = new Orangutan();
    action((T)(orangutan as IAnimal));  // needs to be cast as IAnimal

    //This doesn't work either:
    IAnimal animal = new Orangutan();
    action((T)animal);  // needs to be cast as T
}

It also seems like the fact that it's an interface makes a difference. If you had an abstract class Animal, instead of an interface, you could do this:

public abstract class Animal { }
public class Orangutan : Animal { }

public void ValidateUsing<T>(Action<T> action) where T : Animal
{
    Orangutan orangutan = new Orangutan();
    action(orangutan as T); 

    //This doesn't work either:
    Animal animal = new Orangutan();
    action(animal as T); 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号