我對方差的經驗很少,但在閱讀了一段時間後,我相信至少理解了基本概念(即方差描述了兩種類型的關係和這兩種類型的關係類似的預測)之間的關係。但是,我似乎無法理解定義爲逆變的意義或好處。乍一看,這實際上似乎阻礙了子類型之間的可比性。我希望有人能夠對此事發表一些看法。IComparable <T>作爲逆變的好處?
4
A
回答
6
我會首先處理IComparer<T>
- 在你的問題中沒有提到,但是這是一個稍微簡單的「銷售」,然後導致IComparable<T>
。
假設你有三類:
- 形狀(有小區物業)
- 圈:外形
- 廣場:外形
可以很容易地編寫一個AreaComparer : IComparer<Shape>
。
逆變讓您排序List<Circle>
面積,因爲IComparer<Shape>
(如AreaComparer
)可轉換爲IComparer<Circle>
。
同樣的IComparable<T>
- 如果Shape
自己宣佈自己IComparable<Shape>
使用Area
,然後再次你可以排序List<Circle>
,因爲每個圓圈絕不會比自己的形狀。
現在很多時候這實際上並不是問題,因爲您將從Circle
到Shape
的隱式轉換。但是將Circle
的自然能力視爲IComparable<Circle>
可能有助於泛型方法的類型推斷。例如,假設我們有:
void Foo<T>(IComparable<T> item1, T item2)
我們嘗試調用
Foo(circle1, circle2);
我不知道隨便編譯器是否會(無逆變)能夠推斷T=Shape
,這是可行的。 ..但即使它可能,它會失敗:
void Foo<T>(IComparable<T> item1, T item2) where T : ISomethingCircleImplements
我們真的希望編譯器很樂意與T=Circle
,我建議 - 這是隻要有效Circle
是IComparable<Circle>
通過協方差。
編輯:下面是它的工作的例子:
using System;
public abstract class Shape : IComparable<Shape>
{
public abstract double Area { get; }
public int CompareTo(Shape other)
{
return Area.CompareTo(other.Area);
}
}
public interface ISomethingCircleImplements {}
public class Circle : Shape, ISomethingCircleImplements
{
private readonly double radius;
public Circle(double radius)
{
this.radius = radius;
}
public override double Area { get { return radius * radius * Math.PI; } }
}
class Test
{
static void Foo<T>(IComparable<T> item1, T item2)
where T : ISomethingCircleImplements
{
Console.WriteLine(item1.CompareTo(item2));
}
static void Main()
{
Circle c1 = new Circle(10);
Circle c2 = new Circle(20);
Foo<Circle>(c1, c2);
}
}
有趣的是,類型推斷不在這裏工作 - 但我不知道爲什麼。反轉本身雖然很好。
相關問題
- 1. FxCop和IComparable/IComparable <T>
- 2. IDictionary <,>逆變?
- 3. 實現IComparable的<T>
- 4. IComparable與IComparable之間的區別<K>
- 5. List <int> to IEnumerable <IComparable>
- 6. C#-IComparable <T>和IEquatable <T>
- 7. 爲什麼是List <>。OrderBy LINQ比IComparable + List <>更快。
- 8. F# - >實現HashSet的IComparable <'a>
- 9. Keystate逆變器不工作
- 10. 逆變不起作用
- 11. IComparable IgnoreCase
- 12. 逆小波變換[/ xpost信號處理]
- 13. 不能設置爲空的特性「TGT」
- 14. IComparable <T>繼承或接口?
- 15. SortedList只需要IComparable <T>
- 16. tomcat的好處或好處copyXML = true屬性<Host>元素
- 17. 運行Apache作爲服務的好處?
- 18. 爲什麼參數處於逆變位置?
- 19. Active記錄中不可逆遷移的好處?
- 20. 與Angular一起使用呃逆的實際好處是什麼?
- 21. 爲什麼不IEnumerable <T>。最大限制T是IComparable?
- 22. 繼承的逆變
- 23. 逆變的例子
- 24. Scss變量的好處?
- 25. 逆變和Val
- 26. 逆變哪裏?
- 27. 部隊更新TGT
- 28. IComparable的和equals()
- 29. 內置「< >比較」不適用於「IComparable <T>」?
- 30. 從sympy逆拉普拉斯變換獲得更好的答案
Jon,現在已經多次閱讀您的回覆,我認爲這實際上已經開始有意義了。謝謝! – blf 2012-08-03 13:17:32
喬恩,看起來好像我過早接受了你的答案。仍然發現自己有問題,我花了一些時間來實施涉及擬議的Foo示例的測試案例。它不會編譯錯誤,「類型'Testable.Shape'不能用作通用類型或方法'Testable.Test.Foo (System.IComparable ,T)'中的類型參數'T''。沒有從'Testable.Shape'到'Testable.ISomethingCircleImplements'的隱式引用轉換「 –
blf
2012-08-09 13:13:28
@blf:是的,但你不想在那T = Shape。你想要T = Circle,它只有在Circle實現'IComparable'時纔有效,它只通過反轉來實現。 –
2012-08-09 13:56:56