dek dek - 14 days ago 5
C# Question

How to add constraints to non generic methods or something close to this feature

Given a Generic class with some methods. Based on the "Generic class of type", I would like to use the appropriate methods. Is there a way to achieve this functionality?

for example:

public interface IType {}
public class TypeA : IType { }
public class TypeB : IType { }

public class Worker<T> where T : IType
{
private string _msg;

public Worker<T> DoWorkA(string input) where T : TypeA
{
_msg = input;
return this;
}
public Worker<T> DoWorkA2(string input) where T : TypeA
{
_msg += input;
return this;
}
public Worker<T> DoWorkB(string input) where T : TypeB
{
_msg = input;
return this;
}

public void DoWork()
{
Console.WriteLine(_msg);
}
}


// usage

// this should work

var worker = new Worker<TypeA>().DoWorkA("Doing").DoWorkA2(" A class work");
worker.DoWork();


// this should NOT work

var worker = new Worker<TypeA>().DoWorkB("Doing B class work");
worker.DoWork();

Answer

You might want to switch to a non-generic class with generic methods. There you can add individual constraints:

public class Worker
{
    private string _msg;

    public Worker<T> DoWorkA<T>(string input) where T : TypeA
    {
        _msg = input;
        return this;
    }
    public Worker<T> DoWorkB<T>(string input) where T : TypeB
    {
        _msg = input;
        return this;
    }

    public void DoWork()
    {
        Console.WriteLine(_msg);
    }
}

UPDATE:

According to your comment you don't want to include type parameters in each call to the generic methods. That is not an issie, if you pass instances of your class to the worker methods, because the type can then be inferred:

public class Worker
{
    public Worker<T> DoWorkA<T>(T value) where T : TypeA
    {
        _msg = input;
        return this;
    }
    public Worker<T> DoWorkB<T>(T value) where T : TypeB
    {
        _msg = input;
        return this;
    }
}

In this case the type parameter can be inferred:

Worker worker = new Worker();
TypeA a = new TypeA();
worker.DoWorkA(a);

You could do it also with extension methods:

public static class Worker
{
    public static Worker<T> DoWorkA<T>(this T value) where T : TypeA
    {
        _msg = input;
        return this;
    }
    public static Worker<T> DoWorkB<T>(this T value) where T : TypeB
    {
        _msg = input;
        return this;
    }
}

Which you can call like this:

TypeA a = new TypeA();
a.DoWorkA();
Comments