views:

134

answers:

4

Here is an example :

public class B<T> {}
public class D : B<int> {}
public class A<T, S> where T : B<S> {}
public class C : A<D, int> {}

public class Test1
{
    public class test1
    {
        A<D, int> t = new C();
    }
}

What I would like do to is in declaring class C, only say : C : A<D>. Why I need to repeat int ? Because int is already a part of D.

Same in the test1 method. I would like to write : A<D> t = new C();

How, can I achieve that ?

UPDATE

Here with more realistic class names :

public class MyModel<T> { }
public class MyTrueModel : MyModel<int> { }

public class MyManager<T,S> where T : MyModel<S> { }
public class MyTrueManager : MyManager<MyTrueModel, int> { }

public class Test1
{
    public class test1
    {
        MyManager<MyTrueModel, int> t = new MyManager<MyTrueModel, int>();
    }
}

All the problem come from the class MyManager. If I was able to do something like : MyManager<T> where T : MyModel it'd would be great.

A: 

Probably I missunderstood your question. But if you do not need int. Just use D.

public class B<T> { }
public class D : B<int> { }
public class A<T> where T : D { }
public class C : A<D> { }
public class Test1 { public class test1 { A<D> t = new C();    } }
Mike Chaliy
A: 

Declare A as:

public class A<T> where T : B<S>

Should work, but I don't have a compiler on me so I can't say for sure.

Anon.
I don't think this will compile: the compiler has no way to resolve S.
itowlson
It can resolve S just as easily as it can resolve T, no?
Anon.
@Anon. No. If this were legal then I could say `A<int> a = new A<int>();` But now what binds `S`?
Jason
...unless I am grossly mistaken, `int` does not inherit from `B(S)`.
Anon.
But how can the compiler know that? It doesn't even know what `S` is. Don't use `int` if that will satisfy you. Here: `interface IDoNothing<U> { }`, `class A<T> where T : IDoNothing<U> { }` (what is `U`?) and `class C : IDoNothing<short>, IDoNothing<int>`. Finally, `A<C> a = new A<C>`. Well, `C` implements both `IDoNothing<short>` and `IDoNothing<int>` so which type (`short` or `int`) do we use for the unbound type variable `U`?
Jason
Things get funky when we start talking about conflicting interfaces no matter which way you slice it. Suppose two interfaces define methods that are identical except for their return type - what return type should the implementor provide?
Anon.
@Anon.: In that case one of the interfaces will have to be implemented explicitly.
Jason
A: 

A<D> t = new C(); won't work because you have previously declared A to require two generic parameters.

You could declare something like:

class A2<T> : A<T, int> {}

Then (I think) you could achieve A2<D> t = new C();, but I'm assuming that the compiler is smart enough to realize that A2 is compatible with C ... it may not be.

Is this an experiment? Looks like you might have trouble figuring out what this is supposed to do 6 months from now (or even 2 months from now :)

Seth
`A2<D> t2 = (A2<D>) ((A<D, int>) new C());` seems to work with A2 defined as above, but it's certainly not better :P
Seth
+3  A: 

Here's your code:

public class B<T> {}
public class D : B<int> {}
public class A<T, S> where T : B<S> {}
public class C : A<D, int> {}
public class Test1 {
    public class test1 {
        A<D, int> t = new C();
    }
}

Here's equivalent code:

public class B<T> {}
public class D : B<int> {}
public class A<U, V> where U : B<V> {}
public class C : A<D, int> {}
public class Test1 {
    public class test1 {
        A<D, int> t = new C();
    }
}

The point is that the U in A<U, V> is a dummy. When you replace U with T (and V with S) and write A<T, S> the T does not refer to the same T in B<T>. This is why you must use C : A<D, int>. If you were to only write A<D> the compiler does not know (and nor should it; see my comment below on free versus unbound variables) that you want to use int for T in B<T>.

All the problem come from the class MyManager. If I was able to do something like : MyManager<T> where T : MyModel it's would be great.

This is not possible. MyModel is not declared as a type. Only MyModel<T> is a type. More specifically, it is an unbounded generic type. When you specify a type argument (e.g., MyModel<int>) then it will be a constructed type.

At this risk of confusing you further (on this admittedly confusing issue), it might help you read about free and unbounded variables.

Jason
Thanks for your long answer. It's help me to understand. Do you know if there's some workaround I can do to achieve what I want to do ?
Melursus