将泛型类类型转换为其基类失败

时间:2018-03-10 06:30:42

标签: c# .net generics

我正在尝试将泛型类型转换为从它继承的非泛型类型,但它失败了。检查以下代码:

    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``也总是为空。

1 个答案:

答案 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

相关问题