Home > Blockchain >  C# Generic method param
C# Generic method param

Time:03-29

I'm trying to create a simple service where derived classes can override a virtual method by passing in its own objects. Cant seem to get the syntax right. Please see the codes below:

So the base class is as follows:

public class FooBase
{
    public virtual Task StartFooAsync<TParam>(TParam param) where TParam : IFooParam
    {
        Console.WriteLine(param.GetType());
        return Task.CompletedTask;
    }
}

And the IFooParam interface:

public interface IFooParam
{
    public string Title { get; set; }
}

And the class that implements this simple interface is:

public class FooParam : IFooParam
{
    public string Title { get; set; }
}

Now when I try to inherit the FooBase class as:

public class FooOne : FooBase
{
   public override Task StartFooAsync(FooParam param) // wont compile :(
   {
       return base.StartFooAsync(param);
   }
}

I get compile time error telling me there's no suitable method to override for StartFooAsync

The goal here is to inherit from the FooBase class and provide own implementation with its preferred type as parameter for StartFooAsync

CodePudding user response:

No, if the virtual method is a generic method, the override has to be as well. A generic method allows the caller to specify the type argument.

Here's an example of why your code can't work... this should be entirely valid:

class OtherParam : IFooParam
{
    public string Title { get; set; }
}

FooBase x = new FooOne(); // FooOne derives from FooBase
var p = new OtherParam { Title = "xyz" };
x.StartFooAsync<OtherParam>(p);

There's nothing in the declaration of FooBase that would stop that from compiling... but you haven't provided an implementation of StartFooAsync that can handle OtherParam.

One alternative approach is to make FooBase generic instead:

public class FooBase<TParam> where TParam : IFooParam
{
    public virtual Task StartFooAsync(TParam param)
    {
        ...
    }
}

Then your FooOne would derive from FooBase<FooParam>. That would prevent the broken code I showed before, because x would to be declared as either FooBase<FooParam> or FooOne, and the StartFooAsync method would only accept FooParam.

  • Related