【问题标题】:define generic cast for all castable types为所有可转换类型定义通用转换
【发布时间】:2021-05-30 18:54:29
【问题描述】:

我有以下通用类:

public class InclusionData<T>
{
    public T ThisObject { get; private set; }
    public T CopiedFromObject { get; private set; }
    public object OverwrittenOriginal { get; private set; }

    internal InclusionData(T thisObj, T copiedFromObj, object ovrwrtnOrgnl)
    {
        ThisObject = thisObj;
        CopiedFromObject = copiedFromObj;
        OverwrittenOriginal = ovrwrtnOrgnl;
    }
}

我希望这个类可以转换为任何InclusionData&lt;S&gt;,其中T 可以转换为S。我该怎么做?

(*不需要是显式/隐式转换,只需某种方式放入 InclusionData&lt;T&gt; 并取出具有相同内容的 InclusionData&lt;S&gt;。)

我尝试在InclusionData 中定义一个转换方法,如下所示:

public InclusionData<S> Cast<S>() where T : S
{
    return new InclusionData<S>((S)ThisObject, (S)CopiedFromObject, OverwrittenOriginal);
}

但它给出了编译器错误:

  • where T : S 中的T 标记为红色,表示'InclusionData&lt;T&gt;.Cast&lt;S&gt;()' does not define type parameter 'T'
  • (S)ThisObject 和其他两个演员被标记为红色,说cannot convert type 'T' to 'S'

看来,虽然T 已经是一个类型参数,但我无法使用TS 定义约束。那么如何指定S 必须可转换为T

【问题讨论】:

  • 如果你使用一个接口,你可以让它协变IInclusionData&lt;out T&gt;,然后IInclusionData&lt;Cat&gt;可以直接转换为iInclusionData&lt;Animal&gt;

标签: c# generics casting type-conversion


【解决方案1】:

正如另一个答案所说,T : S 不是该方法可能的通用约束,因为它约束T,这是类的通用参数,而不是方法。你只能约束S

我会为此创建两个静态方法。这样,调用者可以指定他们想要转换的类型,并通过这样做,他们选择正确的方法:

// "casting" from superclass to subclass
public static InclusionData<S> Copy<S>(InclusionData<T> other) where S : T {
    return new InclusionData<S>((S)other.ThisObject, (S)other.CopiedFromObject, other.OverwrittenOriginal);
}

// "casting" from subclass to superclass
public static InclusionData<T> Copy<S>(InclusionData<S> other) where S : T {
    return new InclusionData<T>(other.ThisObject, other.CopiedFromObject, other.OverwrittenOriginal);
}

示例用法:

var d1 = new InclusionData<object>("Hello", "World", "Something");
// I can convert from object to string...
InclusionData<string> d2 = InclusionData<object>.Copy<string>(d1);
// and from string to object
d1 = InclusionData<object>.Copy<string>(d2);

请注意,这不处理值类型之间的内置转换,例如 intlong 之间的转换,或任何用户定义的转换运算符。那些你必须自己硬编码的。

【讨论】:

    【解决方案2】:

    这是不可能的:

    public InclusionData<S> Cast<S>() where T : S
    

    因为 T 是具有约束的类型,但 T 没有在方法级别定义。它是在类级别定义的。 例如,这是可能的

    public InclusionData<S> Cast<S>() where S : T
    

    S(在方法级别定义的类型)将具有成为 T(在类级别定义)的子级的约束。

    在所有其他编译错误都消失之后,但我不知道这是否是您想要实现的目标?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多