【问题标题】:How to cast a Generic<T> to a Generic<R> where T is a subclass of R?如何将 Generic<T> 转换为 T 是 R 的子类的 Generic<R>?
【发布时间】:2013-08-15 20:18:43
【问题描述】:

有没有办法定义显式转换器或任何类似的东西,以便编译器可以自动从Generic&lt;R&gt;where T : R 填充Generic&lt;T&gt;

我得到的错误信息是:

值“Reference1[Dog]" is not of type "Reference1[Pet]”,不能在这个通用集合中使用。

我的参考类如下所示:

public interface IReference<T>
{
    T Value { get; }
}

public class Reference<T> : IReference<T>
{
    #region Properties
    public string ref_type { get; set; }
    public string ref_id { get; set; }
    public Uri href { get; set; }

    private bool resolved = false;
    private T _value = default(T);

    public T Value
    { 
        get
        {
            if( !resolved && href != null ) resolve();
            else if( href == null ) return null;
            return _value;
        }
    }
    #endregion

    #region Constructors
    public Reference() { }
    public Reference(string ref_id) 
    {
        this.ref_id = ref_id;
    }
    #endregion

    #region members
    private void resolve()
    {
        if( href != null )
        {
            _value = APIRequestMethods.GetUri<T>(href);
            resolved = true;
        }
        else
            throw new Exception("Cannot resolve the reference because the href property has not been set.");
    }
    #endregion
}

【问题讨论】:

  • co/contra 方差可能是一个答案,具体取决于代码/需要 Generic&lt;in T&gt;Generic&lt;out T&gt;...
  • 否,除非Generic 是一个接口并且类型参数是协变的。
  • 顺便说一句,你知道 Lazy 吗?
  • @Slugart 我不知道!我会考虑在我的实现中使用它。

标签: c# generics inheritance


【解决方案1】:

这只有在你的泛型类型是一个接口并且你使你的泛型类型协变时才有效,即:IGeneric&lt;out T&gt;

请注意,这仅适用于接口或委托。详情请见Covariance and Contravariance in Generics

【讨论】:

  • 我已经包含了我的定义。它应该是一种延迟加载任意类型对象的方法(通过rest API)
  • @Alain 如果您使用IReference&lt;out T&gt;,并且始终使用该界面,它可以工作。
  • 如果我这样做public List&lt;IReference&lt;Pet&gt;&gt; pets = new List&lt;Reference&lt;Pet&gt;&gt;();,我会得到Cannot implicitly convert type 'List&lt;Reference&lt;Pet&gt;&gt;' to 'List&lt;IReference&lt;Pet&gt;&gt;'。当我做public List&lt;IReference&lt;Pet&gt;&gt; pets = new List&lt;IReference&lt;Pet&gt;&gt;(); 时,我得到Cannot create an instance of the abstract class or interface(当然)。
  • @Alain 你可以做List&lt;IReference&lt;Pet&gt;&gt; pets = new List&lt;IReference&lt;Pet&gt;&gt;(); - 这会奏效。然后添加:pets.Add(new Reference&lt;Dog&gt;(new Dog()));
  • 这非常复杂,因为 JSON 反序列化器不够聪明,无法在反序列化引用列表时尝试创建此接口的新实例,这迫使我创建类似于 Activator.CreateInstance(typeof(Reference&lt;&gt;).MakeGenericType(t)); 的复杂代码,但我离题了。这当然是正确的方向,我想我可以看到隧道尽头的曙光。感谢您提供这种方法的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多