alh84001
alh84001

Reputation: 1283

(Re)using generic parameters of a constraining type without declaring them

It probably isn't possible, but I want to check if something like this can be expressed in a simple way:

// obviously doesn't work
class Foo<T> : IFoo<T1,T2>
    where T: Bar<T1,T2>
{
    // ...
    Baz<T1,T2> getBaz(){...}
}

Right now I declare Foo<T1,T2>, but I don't like it semantically, and the only way to get the constraint is to also list Bar in Foo's generic parameter list and I am looking to reduce the redundancy, not add to it.

EDIT: Baz<T1,T2> should be a return type, not method name

Upvotes: 1

Views: 136

Answers (3)

SwDevMan81
SwDevMan81

Reputation: 50018

You could create a wrapper class around it, but I doubt this is better than your original solution:

  public class FooWrapper<T1, T2>
  {
     public Foo<Bar<T1, T2>> FooObj;

     public FooWrapper()
     {
        FooObj = new Foo<Bar<T1, T2>>();
     }

     public class Foo<T> : IFoo<T1, T2> where T : Bar<T1, T2>
     {
        // ...
        public void Baz() 
        {
           Type t1 = typeof(T1);
           Type t2 = typeof(T2);
        }
     }
  }

Upvotes: 1

Jon Hanna
Jon Hanna

Reputation: 113342

The problem with this, is that it doesn't define what T1 and T2 are.

You could do:

class Foo<T> : IFoo<int,string>
    where T: Bar<int,string>
{
    // ...
    void Baz(){...}
    // can call e.g. Qux<int, string>();
}

And you could do:

class Foo<T, T1, T2> : IFoo<T1,T2>
    where T: Bar<T1,T2>
{
    // ...
    void Baz(){...}
    // can call e.g. Qux<T1, T2>();
}

But as it is, there's no way of knowing what T1 and T2 are (a human can't even guess at what you're trying to do, so there's no way for the compiler to deduce it).

Upvotes: 4

Philip Rieck
Philip Rieck

Reputation: 32568

The type parameters required to create a runtime type for a given generic must be declared in the angle brackets with the generic's class name:

class Foo<T, T1, T2> : IFoo<T1, T2> 
          where T: Bar<T1, T2>
{
   //...
   void Baz() {...}
}

Basically, since Foo<x,y,z> is unique for any given combination of x, y, and z, they must all be declared "up top".

Note that you don't need to declare 'T1, T2' with Baz, however - those type parameters are already defined for the class. You can find more in the ECMA spec for generics

Upvotes: 1

Related Questions