0

Given the following code:

namespace sample
{
    class a { }

    class b : a { }

    public class wrapper<T> { }

    class test
    {
        void test1()
        {
            wrapper<a> y = new wrapper<b>();
            //Error 11  Cannot implicitly convert type 'sample.wrapper<sample.b>' to 'sample.wrapper<sample.a>' 
        }
    }
}

Logically speaking, a since b is a, a wrapper<b> is a wrapper<a>. Then why I can't make this conversion, or how can I make it?

Thanks.

LMB
  • 1,137
  • 7
  • 23

3 Answers3

3

since b is a, a wrapper<b> is a wrapper<a>

Well, this is not true for .NET generic classes, they can't be co-variant. You can achieve something similar using interface covariance:

class a { }
class b : a { }

public interface Iwrapper<out T> { }
public class wrapper<T> : Iwrapper<T> {}

class test
{
    void test1()
    {
        Iwrapper<a> y = new wrapper<b>();
    }
}
Dennis
  • 37,026
  • 10
  • 82
  • 150
1

This is a matter of covariance.

Class b is an a, but wrapper<b> is not a wrapper<a>.

You can use C# 4's covariance syntax to allow it like so:

public interface IWrapper<out T> { ... }

public class Wrapper<T> : IWrapper<T> { ... }

This will instruct the CLR to see Wrapper<B> as a Wrapper<A>.

(For the record: C# has capitalization conventions; class names are Pascal-cased).

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • 1
    Unfortunately, covariance is about interfaces and delegates only. – Dennis Dec 11 '12 at 12:55
  • Thanks for your help. I know and use the conventions, just in this project it was convenient to drop them, because I use reflection to generate statements in javascript. – LMB Dec 11 '12 at 13:02
0

Lets do a scenario. Lets call the class a Mammal, the class b Dog, and lets say that the wrapper<T> class is List<T>

See what happens in this code

List<Dog> dogs = new List<Dog>();  //create a list of dogs
List<Mammal> mammals = dogs;   //reference it as a list of mammals

Cat tabby = new Cat();
mammals.Add(tabby)   // adds a cat to a list of dogs (!!?!)

Dog woofer = dogs.First(); //returns our tabby
woofer.Bark();  // and now we have a cat that speaks foreign languages

(Paraphrase of my answer on How to store base class children in a dictionary?)

Community
  • 1
  • 1
SWeko
  • 30,434
  • 10
  • 71
  • 106
  • I'm trying to do Dogs to Mammals, not Mammals to Dogs. My question is why Dogs to Mammals is not allowed! Actually, there's no problem in adding a Cat to a List of Mammals, since Mammals is not required to be the same instance of Dogs. But casting Mammals to Dogs or Cats is clearly impossible. – LMB Dec 11 '12 at 13:12
  • If we were able to cast `dogs` to `mammals`, we are then able to add a cat to the list, and via the `dogs` reference, to get it out of the collection as a dog. I've modified the example, I hope is clearer now. – SWeko Dec 11 '12 at 13:21
  • There's no need to Mammals being the same instance of Dogs after the conversion. For example, you can convert a String to a Char[] then modify the chars without modifying the string. You can cast DateTime to String, then change the string without changing the date. – LMB Dec 11 '12 at 13:25
  • Those are value types (or have value type semantics). When using references, the dogs and the mammals lists are the same exact list, just referenced twice. If you would like to copy the dogs to a list of mammals, the C# compiler is perfectly happy with that. The code `List mammals = new List(dogs);` works as expected. – SWeko Dec 11 '12 at 13:30
  • As matter of fact. Using Arrays instead of Lists, your example will compile and run, throwing a Exception when you try to add a Cat to Mammals. – LMB Dec 11 '12 at 13:31
  • I appreciate your help, but this argument is pure rhetoric: A Collection of Dogs is not a Collection of Mammals, because someone in the future might take them for Cats. – LMB Dec 11 '12 at 13:34
  • Yes, in c# arrays are covariant. [Eric Lippert has an explanation](http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx) why it was added and why it is broken. – SWeko Dec 11 '12 at 13:36
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20945/discussion-between-sweko-and-lmb) – SWeko Dec 11 '12 at 13:37