Eduardo Carísio
Eduardo Carísio

Reputation: 415

c# Generic on variable declaration, is this possible?

I have the following problem:

public class MyClass<T> where T : class
{
    private MyOtherClass<T, U> variable where U : class;
    ... content ...
}
public class MyOtherClass<T, U> where T : class where U : class
{
    ... content ...
}

Is that possible somehow?

Upvotes: 4

Views: 10690

Answers (3)

Mathieu Guindon
Mathieu Guindon

Reputation: 71157

To directly answer the question as it is titled, you can't do that becausevariable is a field of type MyOtherClass<T, U>, which means MyOtherClass defines type parameters T and U - as you have it!

The T of MyClass<T> is not the same T as that of MyOtherClass<T, U>, because the declaration of generic type constraints belongs to the generic type itself, not to the types that use it - and that's good!

If it were possible, a type such as this:

public class SomeRepository<TEntity>
    where TEntity : IEntity { /* ... */}

Could possibly be used like this:

public class SomeService
{
    private SomeRepository<TEntity> _someRepo where TEntity : INotAnEntity
}

Interfaces, classes and methods can be generic (i.e. are able to define type constraints); fields and properties can't, but they can be of a generic type.

Upvotes: 1

nmclean
nmclean

Reputation: 7724

It looks like you want MyClass<T> to contain a reference to MyOtherClass<T, U> where both Ts match but any U is accepted. If this is what you're trying to do, the existing answers probably don't help because a method with a generic U parameter still requires the user to specify U.

Classes with type parameters (especially multiple ones) should inherit / implement something less generic to support situations like this. For example:

public interface IOtherThing<T> {
    T Value1 { get; }
    object Value2 { get; }
}

public class MyOtherClass<T, U> : IOtherThing<T> {
    public T Value1 { get { ... } }
    public U Value2 { get { ... } }
    object IOtherThing<T>.Value2 { get { return Value2; } }
}

Now, MyClass<T> can declare a variable as IOtherThing<T>, which can be assigned to any MyOtherClass<T, U>.

Upvotes: 1

p.s.w.g
p.s.w.g

Reputation: 148980

If you want to make the type of a field or property of MyClass generic based on some type parameter U, you have to declare that as a type parameter of MyClass:

public class MyClass<T, U> 
    where T : class 
    where U : class
{
    private MyOtherClass<T, U> variable;
    ... content ...
}
public class MyOtherClass<T, U>
    where T : class 
    where U : class
{
    ... content ...
}

However, that doesn't apply to methods. This is perfectly fine:

public class MyClass<T> 
    where T : class 
{
    private MyOtherClass<T, U> Method<U>() where U : class
    {
        ... content ...
    }
}

Upvotes: 3

Related Questions