gpt4 book ai didi

c# - 为什么 ReSharper 建议我使类型参数 T 逆变?

转载 作者:IT王子 更新时间:2023-10-29 04:06:36 28 4
gpt4 key购买 nike

ReSharper 建议我通过更改以下内容使类型参数 T 逆变:

interface IBusinessValidator<T> where T: IEntity
{
void Validate(T entity);
}

进入这个:

interface IBusinessValidator<in T> where T: IEntity
{
void Validate(T entity);
}

那么<T>之间有什么不同呢?和 <in T> ?这里逆变的目的是什么?

假设我有 IEntity , Entity , UserAccount实体。假设这两个 UserAccountName需要验证的属性。

如何在此示例中应用逆变的用法?

最佳答案

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接口(interface)和一个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> .因为它是逆变,所以我可以通过它BusinessValidator<Entity> .

如果我们删除 in关键字,我们得到以下错误:

Not contravariant

如果我们包含它,编译会很好。

关于c# - 为什么 ReSharper 建议我使类型参数 T 逆变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28687446/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com