繁体   English   中英

有没有一种方法可以在C#中为泛型的特定版本定义隐式转换运算符?

[英]Is there a way to define implicit conversion operators in C# for specific versions of generic types?

我有一个通用类MyClass<T> ,我希望能够从某种类型(例如bool隐式转换为该通用类型的特定版本,例如MyClass<string> 看来我不能使用以下任何一项:

  • 失败,因为“使用通用类型'MyClass <T>'需要类型参数'1'”:

    public static implicit operator MyClass(bool value) { return new MyClass<string>(value.ToString()); }

  • 失败,因为“未绑定的通用名称在此上下文中无效”,并且因为“用户定义的转换必须与封闭类型进行转换”:

    public static implicit operator MyClass<>(bool value) { return new MyClass<string>(value.ToString()); }

  • 失败,因为“用户定义的转换必须与封闭类型进行转换”:

    public static implicit operator MyClass<string>(bool value) { return new MyClass<string>(value.ToString()); }

  • 失败,因为“无法将类型'MyClass <string>'隐式转换为'MyClass <T>'”:

    public static implicit operator MyClass<T>(bool value) { return new MyClass<string>(value.ToString()); }

有什么方法可以实现,还是我将不得不没有它(并在任何地方引起对转换方法的显式调用)?

不,你不能这样做。 C#规范很明确,您的implicit运算符必须在声明它的类型之间进行转换。 它必须是精确的转换,并且由于声明类型恰好是MyClass<T> ,所以转换必须是往返于该类型的。

请参见例如, 我可以使用通用的隐式或显式运算符吗? 具有泛型的 C#C#隐式运算符

冒犯纵容或认可XY问题的风险,这里有一些骇人听闻的选择:

// Break generics by checking the type explicitly. Requires ugly casting
// and intermediate boxing, though it's possible that with some run-time
// use of Expressions, you could cache a delegate that would handle the
// conversion without the boxing. It'd still be ugly though.
class Class1<T>
{
    public Class1(T t) { }

    public static implicit operator Class1<T>(bool value)
    {
        if (typeof(T) == typeof(string))
        {
            return (Class1<T>)(object)(Class1OfString)value;
        }

        throw new InvalidOperationException("Invalid type T");
    }
}

// Subclass the generic, and declare the conversion there. Of course, then
// to use the conversion, you have to reference this type explicitly. Ugly.
class Class1OfString : Class1<string>
{
    public Class1OfString(string text) : base(text) { }

    public static implicit operator Class1OfString(bool value)
    {
        return new Class1OfString(value.ToString());
    }
}

class A
{
    public static void M()
    {
        // These all compile and execute fine
        Class1OfString c1 = true;
        Class1<string> c2 = (Class1OfString)true;
        Class1<string> c3 = true;
    }
}

上面的主题有很多变体,但是它们都会以某种方式涉及规避和特殊类型的变体。

值得指出的是,除了在这里处理通用和特定的困难之外,还有其他原因还可能会使用implicit 该文档在最上方指出,仅在“保证转换不会引起数据丢失的情况下才应使用implicit 而实现应“永远不应引发异常” 在这两种情况下,这都是“以便可以在程序员不知情的情况下安全地使用它们” 换句话说, implicit本质是它们被隐式调用,而程序员甚至不必考虑它。 因此,他们必须工作,这不一定是与上面的一些例子(和一个例子,你无论如何都要使用一个明确的语法,所以你还不如实施操作的情况下, explicit反正)。

这些选项都不是理想的。 但坦率地说,原始情况也不是。 泛型类型必须在特定的基础上处理具体类型是很奇怪的。 它使人们质疑,泛型类型是否真的首先应该是泛型的。 您可能确实应该做更多的事,例如上面的子类化示例,仅进一步应用。 即,将通用类型用于所需的任何基本行为,但是将所有专长都放在一个知道类型参数T的子类中。

鉴于问题中缺少细节,我无法提供更多建议。 但是基本的要求是不稳定的,建议如果仅是问题包含更广泛的问题说明以及导致您实现此实际实现目标的详细信息,则可能会提供更好且更适用的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM