泛型类型上的隐式运算符

发布于 2024-09-25 21:20:35 字数 617 浏览 4 评论 0原文

使用像下面这样的隐式运算符有什么问题吗:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

我想我可以通过这种方式将对象的实例视为值类型,但由于我从未见过这样的示例,所以我想也许有一个原因去做有人可以指出的事情吗?

在我的实际代码中,我正在考虑将其作为数据抽象层的一部分,以便我可以返回具有描述底层数据的信息的对象,但允许逻辑代码在需要了解所有信息时将其视为值类型是值,同时使用泛型保持一切良好和类型安全。

Is there anything wrong with using an implicit operator like the following:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

I was thinking I could treat as instance of the object as a value type this way, but seeing as I've never seen an example of this I thought maybe there was a reason not to do something like this that someone could point out?

In my actual code I was thinking of doing this as part of a data abstraction layer, so that I could return objects with information describing the underlying data, but allow the logic code to treat it as a value type when all it needs to know about is the value, and at the same time keep it all nice and type safe with the generics.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

就此别过 2024-10-02 21:20:35

如果满足以下所有条件:

  • 所有 MyClass 类型的可能值(如果不是值,则包括 null type!) 映射到 T

  • 隐式运算符永远不会抛出异常(甚至对于 null 也不会!)< /p>

  • 隐式转换具有语义意义,并​​且不会让客户端程序员感到困惑

,那么这没有什么问题。当然,您可以做这三件事中的任何一件,但这将是糟糕的设计。特别是,抛出异常的隐式运算符可能很难调试,因为调用它的地方并没有说明它正在被调用。

例如,考虑 T? 没有到 T 的隐式转换(其中 T 当然是值类型)。如果存在这样一个隐式运算符,则当 T? 为 null 时,它必须抛出异常,因为没有明显的值可以将 null 转换为对 T? 有意义的值。 em>任何值类型T


让我举一个例子,我在调试隐式运算符引发的问题时遇到了麻烦:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

这里,GetSomething 返回了我编写的类型,该类型具有用户定义的到 string 的隐式转换代码>.我绝对确定GetSomething永远不会返回null,但我得到了NullReferenceException!为什么?因为上面的代码相当于

return some_condition ? (string)GetSomething() : (string)null;

但是

return (string)(some_condition ? GetSomething() : (Something)null);

现在你可以看到null来自哪里了!

If all of the following are true:

  • all possible values of your MyClass<T> type (including null if it’s not a value type!) map to a valid value of T

  • the implicit operator never throws (not even for null!)

  • the implicit conversion makes semantic sense and is not confusing to the client programmer

then there is nothing wrong with this. Of course you could do any of these three things, but it would be bad design. In particular, an implicit operator that throws can be very hard to debug because the place where it is called doesn’t say that it is being called.

For example, consider that T? has no implicit conversion to T (where T is, of course, a value type). If there was such an implicit operator, it would have to throw when the T? is null, as there is no obvious value to convert null to that would make sense for any value type T.


Let me give an example where I had trouble debugging an issue where the implicit operator threw:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

Here, GetSomething returned something of a type I wrote which has a user-defined implicit conversion to string. I made absolutely sure that GetSomething could never return null, and yet I got a NullReferenceException! Why? Because the above code is not equivalent to

return some_condition ? (string)GetSomething() : (string)null;

but to

return (string)(some_condition ? GetSomething() : (Something)null);

Now you can see where the null came from!

蹲墙角沉默 2024-10-02 21:20:35

这是一个很棒的模式。请记住,为了将其用作 T 类型的变量,您必须将其显式转换为 T,或者将其分配给 T 类型的变量代码>T。转换将在方法调用和其他采用 T 的事情(例如您的加法示例)中自动进行。

无需赋值的隐式转换?

That's a great pattern. Just keep in mind that in order to use it as a variable of type T, you have to either explicitly cast it to T, or assign it to a variable of type T. The cast will take place automatically in method calls and other things (such as your addition example) that take a T.

Implicit conversion without assignment?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文