Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you satisfy a generic constraint with an implicit conversion?

Given these types:

class A { }
class B
{
    public static implicit operator A(B me)
    {
        return new A();
    }
}

class Test<T> where T : A { }

I tried

var b = new Test<B>();

And expected it to fail, which it did. But the error message is

The type 'B' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'B' to 'A'.

But there is an implicit reference conversion from B to A. Is this just a strange message? There is not an implicit reference conversion as Adam Robinson's answer shows. The message is correct.

Note that MSDN says:

where T : (base class name) - The type argument must be or derive from the specified base class.

Which explains why it is not allowed since B does not derive from A

like image 394
default.kramer Avatar asked Nov 17 '11 18:11

default.kramer


People also ask

Can generic classes be constrained?

You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.

What is generic type constraint?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)

Which of the following keyword is used to apply constraints on type parameter?

By using where keyword, we can apply constraints on generics. In c#, you can apply multiple constraints on generic classes or methods based on your requirements. In c#, you have a different type of constraints available; those are class, structure, unmanaged, new(), etc.


1 Answers

No, what you're trying to do is not possible. An implicit reference conversion is not the same thing as an implicit type conversion. Your code defines an implicit type conversion, which is where you could do the following:

B foo = new B();
A bar = foo;

Note, however, that foo and bar now contain different references. The implicit type conversion creates a new instance of A that should be (by convention) logically equivalent to foo. But the point is that it's a different reference.

A reference conversion would be where the reference itself does not change, which means that the type in question must either inherit from (for classes) or implement (for interfaces) the type in question. If I do this:

class A { }
class B : A { }

Then my code above will now hold the same reference in foo and bar. This is what is meant by an implicit reference conversion. Conversely, an explicit reference conversion would be downcasting, like this:

A foo = new B();
B bar = (B)foo;

Again, the references are the same, but the cast was explicit.

So, in short, the MSDN documentation is clearer but less precise.

like image 63
Adam Robinson Avatar answered Nov 14 '22 21:11

Adam Robinson