So what is different between <T> and <in T>?
不同的是,in T
允許你傳遞一個更通用的(少派生)類型比指定什麼。
And what is the purpose of contravariant here?
ReSharper的建議在這裏使用逆變,因爲它看到你傳遞的T
參數到的Validate
方法,並希望允許您通過使其不太通用拓寬輸入類型。
一般來說,反向變化在Contravariance explained和Covariance and contravariance real world example中解釋爲長度,當然在整個MSDN文檔中(有一個great FAQ by the C# team)。
有通過MSDN一個很好的例子:
abstract class Shape
{
public virtual double Area { get { return 0; }}
}
class Circle : Shape
{
private double r;
public Circle(double radius) { r = radius; }
public double Radius { get { return r; }}
public override double Area { get { return Math.PI * r * r; }}
}
class ShapeAreaComparer : System.Collections.Generic.IComparer<Shape>
{
int IComparer<Shape>.Compare(Shape a, Shape b)
{
if (a == null) return b == null ? 0 : -1;
return b == null ? 1 : a.Area.CompareTo(b.Area);
}
}
class Program
{
static void Main()
{
// You can pass ShapeAreaComparer, which implements IComparer<Shape>,
// even though the constructor for SortedSet<Circle> expects
// IComparer<Circle>, because type parameter T of IComparer<T> is
// contravariant.
SortedSet<Circle> circlesByArea =
new SortedSet<Circle>(new ShapeAreaComparer())
{ new Circle(7.2), new Circle(100), null, new Circle(.01) };
foreach (Circle c in circlesByArea)
{
Console.WriteLine(c == null ? "null" : "Circle with area " + c.Area);
}
}
}
How can I apply the usage of contravariant in this example?
比方說,我們有我們的實體:
public class Entity : IEntity
{
public string Name { get; set; }
}
public class User : Entity
{
public string Password { get; set; }
}
我們也有一個IBusinessManager
接口和BusinessManager
實現,它接受一個IBusinessValidator
:
public interface IBusinessManager<T>
{
void ManagerStuff(T entityToManage);
}
public class BusinessManager<T> : IBusinessManager<T> where T : IEntity
{
private readonly IBusinessValidator<T> validator;
public BusinessManager(IBusinessValidator<T> validator)
{
this.validator = validator;
}
public void ManagerStuff(T entityToManage)
{
// stuff.
}
}
現在,讓我們說,我們創建了一個通用驗證任何IEntity
:
public class BusinessValidator<T> : IBusinessValidator<T> where T : IEntity
{
public void Validate(T entity)
{
if (string.IsNullOrWhiteSpace(entity.Name))
throw new ArgumentNullException(entity.Name);
}
}
而現在,我們想通過BusinessManager<User>
和IBusinessValidator<T>
。因爲它是contravariant,我可以通過它BusinessValidator<Entity>
。
如果我們去掉in
關鍵字,我們得到以下錯誤:
如果包括它,這個編譯罰款。
您是否已閱讀文檔? https://msdn.microsoft.com/zh-cn/library/dd799517(v=vs.110).aspx – 2015-02-24 03:01:21
是的,我已閱讀它。不過,我對理解文章有點問題。無論如何,鏈接有幫助。 – 2015-02-24 08:16:35