Explicit listing required for general with where clause

I hope someone can suggest a way to avoid the explicit cast for the "var o3" statement below. It seems that the compiler should have enough information for implicit casting.

  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) {}
    }

  }
+4
source share
1 answer

You need to add a restriction classon the Tclass type argument Graph<T>:

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

This is because covariance does not work with structs:

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

although both Int32and Stringimplement IConvertible.

See Why covariance and contravariance do not support value type .

+4
source

Source: https://habr.com/ru/post/1527864/


All Articles