简体   繁体   English

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

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

I have a generic class, MyClass<T> , and I want to be able to implicitly convert from some type, eg bool , to a specific version of the generic type, eg MyClass<string> . 我有一个通用类MyClass<T> ,我希望能够从某种类型(例如bool隐式转换为该通用类型的特定版本,例如MyClass<string> It seems I cannot use any of the following: 看来我不能使用以下任何一项:

  • fails because "Using the generic type 'MyClass<T>' requires '1' type argument(s)": 失败,因为“使用通用类型'MyClass <T>'需要类型参数'1'”:

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

  • fails because "Unbound generic name is not valid in this context" and because "User-defined conversion must convert to or from the enclosing type": 失败,因为“未绑定的通用名称在此上下文中无效”,并且因为“用户定义的转换必须与封闭类型进行转换”:

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

  • fails because "User-defined conversion must convert to or from the enclosing type": 失败,因为“用户定义的转换必须与封闭类型进行转换”:

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

  • fails because "Cannot implicitly convert type 'MyClass<string>' to 'MyClass<T>'": 失败,因为“无法将类型'MyClass <string>'隐式转换为'MyClass <T>'”:

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

Is there any way this can be achieved, or will I just have to live without it (and incur explicit calls to a conversion method everywhere)? 有什么方法可以实现,还是我将不得不没有它(并在任何地方引起对转换方法的显式调用)?

No, you can't do this. 不,你不能这样做。 The C# specification is clear, your implicit operator must convert either to or from the type in which it's declared. C#规范很明确,您的implicit运算符必须在声明它的类型之间进行转换。 It has to be an exact conversion, and since the declaring type is exactly MyClass<T> , the conversion has to be either to or from that. 它必须是精确的转换,并且由于声明类型恰好是MyClass<T> ,所以转换必须是往返于该类型的。

See eg Can i use a generic implicit or explicit operator? 请参见例如, 我可以使用通用的隐式或显式运算符吗? C# and C# Implicit operator with generic . 具有泛型的 C#C#隐式运算符

At the risk of condoning or endorsing an XY Problem , here are a couple of hacky alternatives: 冒犯纵容或认可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;
    }
}

There are a number of variations on the themes above, but they all will involve circumventing and special casing the type in some way. 上面的主题有很多变体,但是它们都会以某种方式涉及规避和特殊类型的变体。

It is worth pointing out that, besides the difficulty dealing with the generic vs. specific here, the use of implicit is suspect for other reasons. 值得指出的是,除了在这里处理通用和特定的困难之外,还有其他原因还可能会使用implicit The documentation states right at the top that one should use implicit only "if the conversion is guaranteed not to cause a loss of data" and implementations "should never throw exceptions" . 该文档在最上方指出,仅在“保证转换不会引起数据丢失的情况下才应使用implicit 而实现应“永远不应引发异常” In both cases, this is "so that they can be used safely without the programmer's awareness" . 在这两种情况下,这都是“以便可以在程序员不知情的情况下安全地使用它们” In other words, the very nature of implicit is that they get invoked implicitly, without the programmer necessarily even thinking about it. 换句话说, implicit本质是它们被隐式调用,而程序员甚至不必考虑它。 So they must always work, which wouldn't necessarily be the case with some of the examples above (and in one example, you have to use an explicit syntax anyway, so you might as well implement the operator as explicit anyway). 因此,他们必须工作,这不一定是与上面的一些例子(和一个例子,你无论如何都要使用一个明确的语法,所以你还不如实施操作的情况下, explicit反正)。

None of these options are ideal. 这些选项都不是理想的。 But frankly, neither is the original scenario. 但坦率地说,原始情况也不是。 It is odd for a generic type to have to deal with concrete types on a specific basis. 泛型类型必须在特定的基础上处理具体类型是很奇怪的。 It calls into question whether the generic type really should be generic in the first place. 它使人们质疑,泛型类型是否真的首先应该是泛型的。 It is possible that you really should be doing something more like the subclassing example above, only applied further. 您可能确实应该做更多的事,例如上面的子类化示例,仅进一步应用。 Ie use the generic type for whatever base behavior you need, but put all your specializations into a subclass where you know the type parameter T . 即,将通用类型用于所需的任何基本行为,但是将所有专长都放在一个知道类型参数T的子类中。

I can't offer more advice than that, given the lack of details in the question. 鉴于问题中缺少细节,我无法提供更多建议。 But the basic request is shaky enough to suggest that, if only the question had included a broader problem statement and details about what led you to this actual implementation goal, a better and more applicable answer might have been provided. 但是基本的要求是不稳定的,建议如果仅是问题包含更广泛的问题说明以及导致您实现此实际实现目标的详细信息,则可能会提供更好且更适用的答案。

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

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