Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# generic typing with multiple class constraints

Tags:

c#

TL;DR

I'd like this to compile in C#

public void some_method< T >() where T : class1, class2

Is this possible?


Full Context

I have two methods that are identical except for one parameter.

public SignInResponseMessage Generate(SignInRequestMessage request, (X509Certificate2 || WindowsPrincipal) principal, Uri requestUri)
{
    SignInResponseMessage response = null;
    ClaimsIdentity identity = null;

    if (principal != null)
    {
        identity = CreateSubject(principal);
        response = Generate(request, requestUri, identity);
    }
    else
    {
        throw new ArgumentNullException("principal");
    }

    return response;
}

I'm currently replicating this method and it's making me cringe a little inside as I would really like to make this DRY-er. Looking around, this documentation seemed promising, but it only allows me to add a single class constraint. I get the following error on the second class:

Error 1 The class type constraint 'class2' must come before any other constraints

If WindowsPrincipal and X509Certificate2 were two classes I had written I could easily make them implement the same interface and I would be good to go, but that's not an option.

Is there any way to accomplish what I'd like to do?

If not, I'd like to know more about the underlying mechanism that makes this impossible.

like image 973
Matt Avatar asked Jan 12 '16 17:01

Matt


1 Answers

I am afraid that this could lead to issues with working out what method to actually call. Imagine if one of the classes specified inherited from the other and there was an override for that method!?

Please see the "Diamond Problem" for a complete description of the reasons

If you want to work around it. You can set up the common shared interface with an adapter and then use that.

interface IAdaper {
    SomeMethod();
}

class AdapterOne : IAdapter {
    TypeOneToCall  _one;

    public AdapterOne (TypeOneToCall one) {
        _one = one;
    }

    public SomeMethod() {
        return _one.SomeMethod();
    }
}

class AdapterTwo : IAdapter {
    TypeTwoToCall _two;

    public AdapterTwo (TypeTwoToCall two) {
        _two = two;
    }

    public SomeMethod() {
        return _two.SomeMethod();
    }
}

class Generic<T> where T : IAdapter {

    // Your implementation here.
}
like image 192
tigerswithguitars Avatar answered Oct 03 '22 02:10

tigerswithguitars