.Net 隐式转换指南

发布于 2024-07-10 22:39:51 字数 157 浏览 6 评论 0原文

关于何时可以、应该或不应该定义用户定义的隐式转换的一般准则是什么?

我的意思是,例如,“隐式转换永远不应该丢失信息”,“隐式转换永远不应该抛出异常”,或者“隐式转换永远不应该实例化新对象”。 我很确定第一个是正确的,第三个不是(或者我们只能隐式转换为结构),而我不知道第二个。

What are general guidelines on when user-defined implicit conversion could, should, or should not be defined?

I mean things like, for example, "an implicit conversion should never lose information", "an implicit conversion should never throw exceptions", or "an implicit conversion should never instantiate new objects". I am pretty sure the first one is correct, the third one is not (or we could only ever have implicit conversion to structs), and I don't know about the second one.

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

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

发布评论

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

评论(4

临风闻羌笛 2024-07-17 22:39:51

第一个并不像您想象的那么简单。 这是一个例子:

using System;

class Test
{
    static void Main()
    {
        long firstLong = long.MaxValue - 2;
        long secondLong = firstLong - 1;

        double firstDouble = firstLong;
        double secondDouble = secondLong;

        // Prints False as expected
        Console.WriteLine(firstLong == secondLong);

        // Prints True!
        Console.WriteLine(firstDouble == secondDouble);        
    }
}

就我个人而言,我很少创建自己的隐式转换。 我对框架中的内容感到非常满意,但我很少觉得添加自己的内容会让生活变得更好。 (顺便说一句,一般值类型也是如此。)

编辑:只是为了实际回答一下这个问题,可能值得阅读 转换运算符是 Microsoft 类库设计指南的一部分

The first isn't as simple as you might expect. Here's an example:

using System;

class Test
{
    static void Main()
    {
        long firstLong = long.MaxValue - 2;
        long secondLong = firstLong - 1;

        double firstDouble = firstLong;
        double secondDouble = secondLong;

        // Prints False as expected
        Console.WriteLine(firstLong == secondLong);

        // Prints True!
        Console.WriteLine(firstDouble == secondDouble);        
    }
}

Personally I very rarely create my own implicit conversions. I'm happy enough with the ones in the framework, but I rarely feel that adding my own would make life better. (The same is true of value types in general, btw.)

EDIT: Just to actually answer the question a bit, it's probably worth reading the conversion operators part of the Microsoft class library design guidelines.

dawn曙光 2024-07-17 22:39:51

我绝对同意第一个观点——大多数情况下是第二个观点(“永不言败”),但不会对第三个观点感到兴奋; 除此之外,它在结构和类之间造成了不必要的区别。 在某些情况下,进行隐式转换可以极大地简化调用约定。

对于显式转换,一切皆有可能。

不过,您并不经常需要编写转换运算符。 在许多情况下,显式运算符更有用,因为如果条件不正确,它们可能会中断(例如,使用 Nullable,如果它们没有值) 。

I'd agree with the first definitely - the second most of the time ("never say never"), but wouldn't get excited by the third; apart from anything else, it creates an unnecessary distinction between structs and classes. In some cases, having an implicit conversion can vastly simplify a calling convention.

For explicit conversions, all things are possible.

It isn't that often you need to write conversion operators, though. And in many cases, explicit operators are more useful, with the acceptance that they can break if conditions aren't right (for example, with Nullable<T>, if they don't have a value).

沧桑㈠ 2024-07-17 22:39:51

如果您只支持自己类型的对象之间的隐式转换,我建议您应该决定哪些“公理”应该应用于此类转换(例如,决定如果 a==b< /code>、b==ca==c 都是合法的,其中两个为真,第三个也必须为真),然后识别使这些公理成立的最有用的转换集。 我在我的博客上讨论了四个有用的公理:http:// supercatnet.blogspot.com/2013/09/axioms-of-implicit-type-conversion.html(不幸的是,.NET Framework 包含违反所有四个的转换,同时不允许不必要的转换)。

需要考虑的重要一点是,在大多数情况下,与不精确类型的隐式转换相比,从不精确类型进行隐式转换会带来更小的意外风险,但有一个值得注意的例外:将更精确类型的某些内容提供给具有重载的方法或运算符,该重载同时采用更精确类型和可以转换为不太精确的类型,某种程度的“令人惊讶”的行为几乎是不可避免的,除非可以使隐式转换变得不可能[例如,如果程序员编写 if (someLong == someFloat) 的行为可能会令人惊讶,但这并不是因为隐式 long 的精度损失float 转换令人惊讶,而是因为人们可能想要通过至少六种不同的方式来比较 longfloat(*),和 any 意味着编译器可能会附加直接比较,这会让那些期待其他东西的人感到惊讶。 据我所知,避免这种惊讶的唯一解决方案是提供重载来显式覆盖所有不明确的情况,并用 [Obsolete()] 标记标记它们。 这样做可能会有些尴尬,但会带来能够满足所有四个公理的巨大优势。

(*) 程序员可能有意测试 long 是否等于四舍五入到最接近的浮点值、向零截断或向负无穷大取整; 或者,程序员可能想要测试 float 是否代表 longfloatlong< /code> 具有相同的标称值,或者 floatlong 是否都会转换为相同的 double

If you will only be supporting implicit conversions among objects of your own types, I would suggest that you should decide on what "axioms" should apply to such conversions (e.g. it may be helpful to decide that if a==b, b==c, and a==c are all legal and two of them are true, the third must also be true) and then identify a the most useful set of conversions which would make those axioms hold. I discuss four useful axioms on my blog at http://supercatnet.blogspot.com/2013/09/axioms-of-implicit-type-conversion.html (unfortunately, the .NET Framework includes conversions which violate all four, while disallows conversions which wouldn't have to).

An important thing to consider is that implicit conversions to imprecise types will in most contexts pose a smaller risk of astonishment than than conversions from imprecise types, but there's a notable exception: if something of a more-precise type is fed to a method or operator which has overloads that take both the more-precise type and a less-precise type to which it can be converted, some level of "astonishing" behavior will be almost inevitable unless one can make implicit conversion impossible [e.g. the behavior if programmer writes if (someLong == someFloat) may be astonishing, but not because the loss of precision on an implicit long to float conversion is astonishing, but rather because there are at least six different ways one might want to compare a long and a float(*), and any meaning the compiler might attach to a direct comparison would astonish those who expected something else. The only solution I know of to avoid such astonishment is to provide overloads to explicitly cover all ambiguous cases and mark them with an [Obsolete()] tag. Doing that is apt to be somewhat awkward, but would offer the substantial advantage of being able to satisfy all four axioms.

(*) A programmer might plausibly be intending to test whether the long was equal to the value of the float rounded to nearest, truncated toward zero, or floored toward negative infinity; alternatively, the programmer might be wanting to test whether the float was the one that represents the long, whether the float and long have the same nominal value, or whether the float and long would both convert to the same double.

余厌 2024-07-17 22:39:51

导致我问这个问题的边缘案例违反了第二个案例。 也就是说,我有一个 Lazy类(不是每个人?)并开始思考我是否不应该提供对 T 的隐式转换。我的直觉是说是,当前版本确实如此,但我不太确定。

The borderline case which caused me to ask this question is a violation of the second one. Namely, I have a Lazy<T> class (doesn't everyone?) and started pondering whether I shouldn't provide an implicit conversion to T. My instinct is to say yes, and the current version does, but I am not too sure.

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