Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the invocation of a generic method allowed inside another generic method?

I'm making a RTS game with Unity. There're many types of resources in my game, such as, tree, farm. Each resource is a GameObject and has it own main script controlling it.

Ex. I want to harvest a tree, I call this.

gameObject.GetComponent<Tree>().Harvest();

If I want to harvest farm I call the same script but change "Tree" to "Farm" which is fine but code will be duplicated. So I abstract it by using generics method like this.

void Harvest<T>(){
    gameObject.GetComponent<T>().Harvest();
}

But the C# compiler won't let me do that. I want to know is it possible to define generics method that use generics method inside? If not, Is there any way to abstract my code like this? Thank you.

Error message:

'T' does not contain a definition for 'Harvest' and no extension method 'Harvest' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) [Assembly-CSharp]

like image 243
Chayanin Avatar asked Mar 04 '26 12:03

Chayanin


1 Answers

The problem is that in ...

void Harvest<T>(){
    gameObject.GetComponent<T>().Harvest();
}

... the C# compiler does not know of which concrete type T will be. Therefore, it cannot know that there will be a method Harvest available, nor does it know its exact declaration (does it return void or bool or something else? Does it have optional arguments?). Because C# is a strongly typed language, this must be known at compile time. This gives you the certainty that everything will go well at runtime.

The solution is to give the compiler a hint by specifying a generic type constraint. To do this you must declare an interface and let the components with a Harvest method implement it.

public interface IHarvestable
{
    void Harvest();
}

Specify the constraint with:

void Harvest<T>() where T : IHarvestable 
{
    gameObject.GetComponent<T>().Harvest();
}

In other situations where you are in control of the base class, you can also declare the required methods in the base class (possibly as abstract) and specify the base class in the generic type constraint instead of an interface.

like image 66
Olivier Jacot-Descombes Avatar answered Mar 07 '26 02:03

Olivier Jacot-Descombes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!