3

This compiles:

    class ReplicatedBaseType
    {
    }

    class NewType: ReplicatedBaseType
    {
    }

    class Document
    {
    ReplicatedBaseType BaseObject;

    Document()
    {
     BaseObject = new NewType();
    }
}

But this does not:

    class DalBase<T> : where T: ReplicatedBaseType
    {
    }

    class DocumentTemplate
    {
    DalBase<ReplicatedBaseType> BaseCollection;
    DocumentTemplate ()
    {
    BaseCollection= new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
    }

What's the reason?

virtualmic
  • 3,173
  • 6
  • 26
  • 34
  • You don't have () after new DalBase ? //edit I've created a project, this is not the case – kubal5003 Jun 25 '10 at 10:58
  • No, no.. that's because I just typed this from memory. Actual code is very long, so didn't duplicate here. Will correct it. Sorry. :( – virtualmic Jun 25 '10 at 11:00
  • possible duplicate of [Explicit Casting Problem](http://stackoverflow.com/questions/1443341/explicit-casting-problem) – thecoop Jun 25 '10 at 11:13

5 Answers5

8

As Andrey says, you want (generic) covariance. However:

  • Generic variance is only supported in C# 4
  • Generic variance isn't supported on classes
  • In your real life case, this may be unsafe.

To go into the final point, suppose DalBase<T> has this method:

void AddEntity(T entity)

Now you've got something like this which you want to be able to compile - but would obviously be dangerous:

DalBase<Fruit> fruitDal = new DalBase<Banana>();
fruitDal.AddEntity(new Apple());

The second line would have to compile - so for this to fail at compile time, it has to be the first line which would fail.

I gave an hour long talk on generic variance recently which you may find useful if you want to know more - see the NDC 2010 video page and search for "variance". Alternatively you could read Eric Lippert's blog posts on the topic - but be aware that that will probably take longer than an hour ;)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
6

Variance exists in C# 4.0 targetting .NET 4), but is limited to interfaces and usage of in/out (oh, and arrays of reference-types). For example, to make a covariant sequence:

class DalBase<T> : IEnumerable<T> where T: ReplicatedBaseType
{
    public IEnumerator<T> GetEnumerator() {throw new NotImplementedException();}
    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}

class DocumentTemplate
{
    IEnumerable<ReplicatedBaseType> BaseCollection;
    DocumentTemplate()
    {
        BaseCollection = new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
}

But other than that... no. Stick to either non-generic lists (IList), or use the expected list type.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

It doesn't work because a DalBase<NewType> is not a DalBase<ReplicatedBaseType> - generics do not have co/contra-variance. In C# 4 you can get generic variance, but only on interfaces and delegates.

thecoop
  • 45,220
  • 19
  • 132
  • 189
1

the feature that you want is called "covariance" and was introduced only in C# 4.0 http://blog.t-l-k.com/dot-net/2009/c-sharp-4-covariance-and-contravariance

you code fails because there is no such cast (both explicit and implicit). Current rules of C# (<= 3.0) forbid it.

to check possible casts see §6.1.6 C# Specification

Andrey
  • 59,039
  • 12
  • 119
  • 163
  • @Marc Gravell♦ i didn't say that. i meant that in C# < 4.0 there is no way to do this casts (well, except for overriding cast operators) – Andrey Jun 25 '10 at 11:04
0

This code compiles in VS2010, net framework 4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class ReplicatedBaseType
    {
    }

    class NewType : ReplicatedBaseType
    {
    }

    class Document
    {
        ReplicatedBaseType BaseObject;

        Document()
        {
            BaseObject = new NewType();
        }
    }
    interface DalBase<out T>  where T: ReplicatedBaseType
    {
    }

    class DalBaseExample<T> : DalBase<T> where T: ReplicatedBaseType
    {

    }
    class DocumentTemplate
    {
        DalBase<ReplicatedBaseType> BaseType;
        DocumentTemplate ()
        {
            BaseType = new DalBaseExample<NewType>(); // no error here
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}
kubal5003
  • 7,186
  • 8
  • 52
  • 90