我遇到了一个泛型问题,我认为可以通过协方差解决,但我不完全了解协方差的工作原理以及如何正确声明它。假设我有以下接口和类:
public interface IOwnedObject<TUser>
where TUser : IBaseUser
{
string UserId { get; set; }
TUser User { get; set; }
}
public interface IBaseUser
{
string Id { get; set; }
}
public class User : IBaseUser
{
public string Id { get; set; }
}
public class SomeOwnedObject : IOwnedObject<User>
{
public string UserId { get; set; }
public User User { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后考虑以下代码:
var obj = new SomeOwnedObject();
if(obj is IOwnedObject<IBaseUser> o)
Console.WriteLine("Success"); // This never executes
Run Code Online (Sandbox Code Playgroud)
上面的if语句的结果不为true。然而,IOwnedObject这只是以往任何时候都可能TUser是IBaseUser。
以下代码评估为true:
var obj = new SomeOwnedObject();
if(obj is IOwnedObject<User> o)
Console.WriteLine("Success"); // This executes
Run Code Online (Sandbox Code Playgroud)
自User工具以来IBaseUser,从IOwnedObject<IBaseUser>技术上讲不应该是的基础类IOwnedObject<User>。是否可以在不引用具体实现的情况下使第一条语句评估为true User?
您可以通过对界面进行一些修改来获得第一个评估结果为true的语句。我们将要TUser使用out关键字将类型标记为协变,这样我们就必须删除属性设置器。
public interface IOwnedObject<out TUser> where TUser : IBaseUser
{
string UserId { get; set; }
TUser User { get; }
}
Run Code Online (Sandbox Code Playgroud)
现在评估
var obj = new SomeOwnedObject();
if (obj is IOwnedObject<IBaseUser> o)
Console.WriteLine("Success");
Run Code Online (Sandbox Code Playgroud)
将导致“成功”被打印到控制台。
| 归档时间: |
|
| 查看次数: |
63 次 |
| 最近记录: |