我正在尝试将泛型类型转换为从它继承的非泛型类型,但它失败了。检查以下代码:
public class Subscription
{
public Subscription(DateTime expiration)
{
Expiration = expiration;
}
public DateTime Expiration { get; set; }
}
public class Subscription<T> : Subscription
{
public T Parameters { get; }
public Subscription(DateTime expiration, T data)
: base(expiration)
{
Parameters = data;
}
}
public class SubscriptionsService
{
private readonly ConcurrentDictionary<int, object> subscriptions;
public SubscriptionsService(ConcurrentDictionary<int, object> subscriptions)
{
this.subscriptions = subscriptions;
}
public void Add<T>(int clientId, DateTime expiration, T parameters)
{
if (!subscriptions.TryGetValue(clientId, out var outObject))
{
Subscription<T> subscription = new Subscription<T>(expiration, parameters);
List<Subscription<T>> clientSubscriptions = new List<Subscription<T>>()
{
subscription
};
subscriptions.AddOrUpdate(clientId, parameters, (k, v) => parameters);
}
else
{
if (outObject is List<Subscription<T>> resourceSubscriptions && resourceSubscriptions.Any())
{
Subscription<T> subscription = resourceSubscriptions.SingleOrDefault(x => x.Parameters.Equals(parameters));
if (subscription == null)
{
subscription = new Subscription<T>(expiration, parameters);
resourceSubscriptions.Add(subscription);
}
else
{
subscription.Expiration = expiration;
}
}
}
}
public void Cleanup()
{
// Iterate through each reportId subscription
foreach (KeyValuePair<int, object> subscriptionKeyValuePair in subscriptions)
{
List<Subscription> subscriptions = (subscriptionKeyValuePair.Value as List<Subscription>);
if (subscriptions == null || !subscriptions.Any())
continue;
foreach (var subscription in subscriptions)
{
if (subscription.Expiration > DateTime.Now)
{
//some code
}
}
}
}
}
当我调用方法Cleanup并遍历keyvalue对时,我试图将字典的值强制转换为非泛型类型,我将其用于将其添加到Add方法中。我添加为List&gt;并尝试将其转换为List以便仅使用Expiration属性,因为我不需要清理中的T参数。结果List<Subscription> subscriptions
强制转换失败,即使字典中的值不是,```susbcriptions``也总是为空。
答案 0 :(得分:0)
您无法进行此投射,因为T
中的List<T>
是一个不变的类型参数。这意味着即使List<A>
派生自List<B>
,C#也不会将A
视为B
的派生类型。
但是,IEnumerable<T>
有一个称为&#34;协变类型参数&#34;的特殊功能。它允许你做这种类型的演员表。这意味着在下面的示例中,带有list1和list2的行将导致编译器错误,但list3可以正常工作。
public class Program<T>
{
public void Main()
{
IList<Subscription> list1 = new List<Subscription<T>>();
List<Subscription> list2 = new List<Subscription<T>>();
IEnumerable<Subscription> list3 = new List<Subscription<T>>();
}
}
public class Subscription<T> : Subscription
{
}
public class Subscription
{
}
有关协方差的更详细说明,请参阅https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance。