1

Can anyone explain why I have to cast to T and why Add2 does not accept Bar as a parameter?

class Foo<T> where T : class, IBar
{
    void Add1(IDo<T> @do) { @do.Stuff(new Bar() as T); }

    // Add2 does not compile:
    // Argument type Bar is not assignable to parameter Type T
    void Add2(IDo<T> @do) { @do.Stuff(new Bar()); } 
}

interface IBar {}

class Bar : IBar {}

interface IDo<in T> {
    void Stuff(T bar);
}
mrt181
  • 5,080
  • 8
  • 66
  • 86

1 Answers1

6

It may not be appropriate. For example, consider:

class Other : Bar {}

...

IDo<Other> do = new DoImpl<Other>();
Foo<Other> foo = new Foo<Other>();
foo.Add2(do);

With your current code, that would be calling do.Add2(new Bar())... which is clearly invalid as a Bar isn't an Other, required by IDo<Other>.Stuff.

Casting to T (or using as) isn't appropriate either - you can't cast a new Bar() to Other, and if you use as you'll just get a null reference.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • `Add2` does not accept an `IBar` or one of it's subclasses. You must give it an `IDo` parameter. – mrt181 Apr 28 '14 at 07:25
  • @mrt181: Yes, sorry - the last call was meant to be `foo.Add2(do);`. Fixed now - and hopefully this shows what's wrong. – Jon Skeet Apr 28 '14 at 07:29