1

私はいくつかのクラスとインターフェースを持っています

public interface IGeoObject
    {
        GeoCoordinate GetGeocoordinate();
    }

public class User : IGeoObject
    {
        public GeoCoordinate GetGeocoordinate()
        {
            //...
            return GeoCoordinate;           
        }
    }  

public class Venue : IGeoObject
    {    
        public GeoCoordinate GetGeocoordinate()
        {
            //...
            return GeoCoordinate;
        }
    }

public class Place : IGeoObject
    {    
        public GeoCoordinate GetGeocoordinate()
        {
            //...
            return GeoCoordinate;
        }
    }

タイプの変数ユーザーの例がありますList<User>

そして、署名付きのメソッドがあります

double GetMinDistance(List<IGeoObject> objects, GeoCoordinate position)

GetMinDistanceジェネリック型の共分散が機能しないため、ユーザーを に渡すことができません。

追加のリストを作成してメソッド.ConvertAll(または.CasT<T>)を使用できます。

List<IGeoObject> list = new List<User>(listUser).ConvertAll(x => (IGeoObject)x);
var dist = GeoTest.GetMinDistance(list, position);

これが最もエレガントなソリューションかどうかはわかりません。呼び出し元がこの変換を行わなければならないことは、最も恥ずかしいことです。

これは、アーキテクチャの問題に似ていますか? よりエレガントなソリューションはありますか?

PS長い話ですが、すべてのクラスで同じ種の座標を与えることはできません。

4

3 に答える 3

8

List<T>共変ではないからです。

public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable

ご覧のとおりout、クラス宣言にはキーワードがありません。

IEnumerable<T>共分散サポートを取得するには、代わりに使用する必要があります。

public interface IEnumerable<out T> : IEnumerable

これList<T>は、コレクションを変更できる一連のメソッドがあり、共分散により、これらの操作のコンパイル タイプ セーフが失われるためです。IEnumerable<T>コレクションを反復処理することしかできないため、共変としてマークすることができます。

于 2013-10-21T23:26:45.110 に答える
3

署名を次のように変更できます。

double GetMinDistance<TGeoObject>(List<TGeoObject> objects, GeoCoordinate position)
    where TGeoObject : IGeoObject 
{
    // ...
}
于 2013-10-21T23:30:01.170 に答える
1

List<User>を受け取って に変換する明示的 (キャスト) または暗黙的な演算子を定義できますList<IGeoObject>

public static explicit operator List<IGeoObject>(List<IGeoObject> ls)
{
  return new ls.ConvertAll(x => (IGeoObject)x);
}
于 2013-10-21T23:25:59.683 に答える