0

I stumbled with this issue, if I define a class

class MyClass<T,U> {
    internal T myEement {get;set;}

    public MyClass(T Element) {
        myEement = Element;
    }
}

And declare extensions.

static class MyClassExtension{


    //What I want to do
    public static void nonWorkingExtension<P,T,U>(this P p, U u) where P:MyClass<T,U>
    {
        T Element = p.myEement;
        //Do something with u and p.Element
    }

    //What I have to do
    public static void workingExtension<P, T, U>(this P p, T dummy, U u) where P : MyClass<T, U>
    {
        T Element = p.myEement;
        //Do something with u and p.Element
    }

}

When calling them:

MyClass<int, double> oClass = new MyClass<int, double>(3);

oClass.workingExtension(0,0.3); //I can call this one.
oClass.nonWorkingExtension(0.3); //I can't call this.

It exits with error.

Error 1 'MyClass' does not contain a definition for 'doSomething' and no extension method 'doSomething' accepting a first argument of type 'MyClass' could be found (are you missing a using directive or an assembly reference?)

After testing I found that the extension must use each generic parameter in a function attribute.

Why is this?

Are there any work arounds?


CONTEXT

Thanks to this answer I was able to implement constrains on generic classes (to make them behave like C++ template specialisation). The solution uses extensions constrains to produce compile time errors on non implemented specialisations.

Community
  • 1
  • 1
xvan
  • 4,554
  • 1
  • 22
  • 37

1 Answers1

1

There's no need to use each generic parameter. Your nonWorkingExtension() must work. I'm pretty sure that the error you're getting is not related to the code you've posted.

Anyway, back to the question. You don't need to use any generic constrains in this code, just use MyClass<T, U> instead:

static class MyClassExtension
{
    public static void nonWorkingExtension<T, U>(this MyClass<T, U> p, U u)
    {
        T Element = p.myEement;
        //Do something with u and p.Element
    }
}
Eldar Dordzhiev
  • 5,105
  • 2
  • 22
  • 26
  • The code I posted crashes on ` nonWorkingExtensions()`. Anyway, I'll check if your suggestion doesn't crash too. – xvan Mar 15 '16 at 22:16
  • @xvan What do you mean by "crashes"? It doesn't compile or what? – Eldar Dordzhiev Mar 15 '16 at 22:18
  • Yes, sorry, it doesn't compile. – xvan Mar 15 '16 at 22:28
  • removing `P` fixes the parameter issue, but I need to keep it to apply specialisation constrains. I tried wrapping `workingExtension()` with the dummy parameter inside your code but it can't find the Extension (the same happens trying to call `workingExtension()` from inside `MyClass`) – xvan Mar 15 '16 at 22:34
  • @xvan That is weird as I can't imagine any reason to put constraints on `P` of an extension method. Anyway, if you want to it this way, you will need to specify the type arguments explicitly every time you call the method. Like this: `oClass.nonWorkingExtension, int, double>(0.3);` – Eldar Dordzhiev Mar 15 '16 at 22:46
  • Look's like *not possible* is the answer to my question. Tried with a wrapping `public static void workingExtension

    (this P p, T dummy, U u) where P : MyClass, SomePolicy` inside `nonWorkingExtension(this MyClass p, U u)` where `MyClass` is a `SomePolicy`, but .net can't resolve P to SomePolicy.

    – xvan Mar 16 '16 at 19:47
  • @xvan It is possible, I've just tried both solutions with an online IDE (mono compiler, but it must work with roslyn as well) – Eldar Dordzhiev Mar 16 '16 at 20:18
  • Opened a follow up for my issue, http://stackoverflow.com/questions/36048248/implementing-multiparameter-c-template-like-behaviour-on-c-sharp-using-policy – xvan Mar 16 '16 at 22:39