在 C# 中是不是可以通过以下方式重载泛型强制转换运算符?

Posted

技术标签:

【中文标题】在 C# 中是不是可以通过以下方式重载泛型强制转换运算符?【英文标题】:Is it possible in C# to overload a generic cast operator in the following way?在 C# 中是否可以通过以下方式重载泛型强制转换运算符? 【发布时间】:2009-06-22 05:30:22 【问题描述】:

只是想知道在 C# 3.5 中是否有任何方法可以表示以下代码:

public struct Foo<T> 

    public Foo(T item) 
        this.Item = item;
    

    public T Item  get; set; 

    public static explicit operator Foo<U> ( Foo<T> a )
        where U : T 

        return new Foo<U>((U)a.Item)
    

谢谢

【问题讨论】:

【参考方案1】:

转换运算符不能是通用的。在规范第 10.10 节中,这是转换操作符声明符的格式:

转换操作符声明符:
    隐式运算符 type ( type identifier )
    显式运算符 type (type identifier)

将其与方法头进行比较:

方法头属性opt 方法修饰符opt 部分opt 返回类型 member-name type-parameter-listopt (formal-parameter-listopt ) 类型参数约束子句opt

(抱歉格式化 - 不知道如何做得更好。)

请注意,运算符格式不包括类型参数列表或类型参数约束。

【讨论】:

即使我们确实支持用户定义的通用转换,这仍然是非法的。定义替换内置转换的转换是非法的。如果 T 和 U 是同一类型,就会这样做;您将替换身份转换。 由于转换是由编译器决定的,如果 T 和 U 是相同的类型,那么它不会使用用户定义的转换,并且是合法的。【参考方案2】:

您的代码归结为:return new Foo&lt;U&gt;((U)a.Item)

您尝试将基类分配给继承的类,这是不可能的。

假设 T(基类)是 Stream 类型,而 U 是 MemoryStream(继承类)类型,您不能将 Stream 分配给 MemoryStream 类型的变量。

【讨论】:

当然可以,如果引用将对象屏蔽为 Stream,但实际上是 MemoryStream,那么您当然可以将其转换为 Memory Stream。这是一种合法的方法,问题是您实际上不能在运算符重载上指定通用约束... ...如果您将我拥有的代码表示为方法而不是运算符重载,它将编译【参考方案3】:

我认为简短的回答是“不可能。尝试改用一种方法”

似乎也被这个问题所欺骗 Solution for overloaded operator constraint in .NET generics

【讨论】:

以上是关于在 C# 中是不是可以通过以下方式重载泛型强制转换运算符?的主要内容,如果未能解决你的问题,请参考以下文章

C#类继承与重载的问题,Mat继承于Matrix,但提示无法将类型隐式转换为 存在一个显式转换 是不是缺少强制转

C#进阶系列11 泛型

接口上的 C# 泛型隐式强制转换失败

为枚举类重载强制转换运算符

C# 泛型重载 List<T> :这将如何完成?

无法用类型约束重载泛型方法[重复]