Matt Frost
Matt Frost

Reputation: 170

Explicit cast required for generic with where clause

I'm hoping someone can suggest a way to avoid the explicit cast for the "var o3" statement below. It seems the compiler should have sufficient information to implicitly cast.

  using System.Collections.Generic;

  namespace Sample {

    public interface IPoint {
      double X { get; }
      double Y { get; }
    }

    public class Line<T> :List<T> where T:IPoint {}

    public class Graph<T> where T :IPoint {
      public Line<IPoint> Line1;
      public Line<T> Line2;

      public Graph() {
        var o1 = new Other(Line1); //works
        var o2 = new Other(Line2 as IEnumerable<IPoint>); //works
        var o3 = new Other(Line2); //error: cannot convert from 'Sample.Line<T>' to 'IEnumerable<Sample.IPoint>'
      }
    }

    public class Other {
      public Other(IEnumerable<IPoint> list) {}
    }

  }

Upvotes: 4

Views: 294

Answers (1)

Athari
Athari

Reputation: 34285

You need to add class constraint on T type argument of Graph<T> class:

public class Graph<T> where T : class, IPoint

This is because covariance doesn't work with structs:

new List<Int32>() is IEnumerable<IConvertible> == false
new List<String>() is IEnumerable<IConvertible> == true

although both Int32 and String implement IConvertible.

See Why covariance and contravariance do not support value type.

Upvotes: 4

Related Questions