使用一元加运算符安全吗?

Is it safe to use the unary plus operator?

提问人:michuu 提问时间:4/6/2023 最后编辑:michuu 更新时间:4/7/2023 访问量:146

问:

我看到的代码是这样的:

double d = GetDouble();
DoSomething(+d);
DoSomething(-d);

我知道其中有潜在的危险,不建议在 C++ 中使用一元只是为了强调值是正的。“只是为了强调价值是积极的”是一种心理捷径。我知道它不会使负值为正值。+<EDIT></EDIT>

C# 语言参考对此没有太多说明:

一元 + 运算符返回其操作数的值。

SO上有一个关于这个问题的问题,但它被标记为C,C++和C#,并且没有一个答案明确提到C#。

C# 一元运算符

评论

1赞 Sami Kuhmonen 4/6/2023
“安全”是什么意思?它存在,它做它所做的事情,如果它以某种方式危险或不被使用,它就不会存在。此外,它不强调值为正数,该值也可以是负数。
4赞 Fildor 4/6/2023
“只是为了强调价值是积极的”——它没有这样做:dotnetfiddle.net/tVbiaQ
1赞 Olivier Jacot-Descombes 4/6/2023
在所有 .NET 数字类型上,一元 + 都是空操作。但是,您可以为自己的类型重载此运算符
2赞 Fildor 4/6/2023
“但是,您可以为自己的类型重载此运算符。”- 对于普通开发人员来说,这将是令人惊讶的,尽管:(
1赞 Sweeper 4/6/2023
你说的“安全”是什么意思?您是否在问它是否具有与 C++ 相同的“潜在危险”效果?如果是这样,C++ 中一元的“潜在危险”影响是什么?请澄清。+

答:

1赞 Peter Csala 4/6/2023 #1

+并且不会更改原始的双精度值,如果这就是您所说的安全。-

double d = 7d;
Console.WriteLine(d);  //7
Console.WriteLine(+d); //7
Console.WriteLine(-d); //-7
Console.WriteLine(d);  //7

//OR
d = -7d;
Console.WriteLine(d);  //-7
Console.WriteLine(+d); //-7
Console.WriteLine(-d); //7
Console.WriteLine(d);  //-7

评论

0赞 michuu 4/6/2023
它是否以任何方式更改了值类型,或者它始终是无操作的?
0赞 Peter Csala 4/6/2023
@michuu否,它不会更改值类型。即使您更改 to 或第一部分也很好用。将导致编译时错误。doubleuintbyted = -7
2赞 Magnetron 4/6/2023
@PeterCsala正如 Sweeper 的回答所指出的,如果变量是 a 或一元将更改为shortbyteint
0赞 Peter Csala 4/6/2023
@Magnetron是的,我看到了。
7赞 Sweeper 4/6/2023 #2

正如您链接的问题的答案所说,C(++) 中的一元确实做了一些事情,并且不一定是无操作。这在 C# 中也是如此。+

C# 只有这些一元运算符(参见规范):+

int operator +(int x);
uint operator +(uint x);
long operator +(long x);
ulong operator +(ulong x);
float operator +(float x);
double operator +(double x);
decimal operator +(decimal x);

因此,如果 是 ,则类型为 ,因为第一个运算符是通过重载解析选择的。因此,像这样的东西不会编译:xshort+xint

short x = 1;
short y = +x;

除其他外,这也会影响过载分辨率。就像此答案中显示的代码一样,如果您这样做:

public class C {
    public static void Foo(int x) {
        Console.WriteLine("int");
    }
    
    public static void Foo(short x) {
        Console.WriteLine("short");
    }
}

C.Foo(x)其中 a 将打印 ,但将打印 。xshortshortC.Foo(+x)int

像上述这样的情况是否经常发生,以至于造成“坏”或“不安全”的做法?这是由你来决定的。+x

当然,如果是自定义结构/类类型,那么基本上可以做任何事情。一元是可重载的。x+x+

评论

0赞 michuu 4/6/2023
这种类型更改行为是否使 C# 社区中不推荐使用?
1赞 Sweeper 4/6/2023
@michuu 不,据我所知。像 这样的情况并不多,其中存在过载和执行完全不同操作的过载。毕竟,重载应该做类似的事情。因此,即使你调用了“错误”的,它的行为仍然应该相同(只是额外无用的转换)。当类型真正重要时,最好为方法提供不同的名称。C.Foointshort
0赞 michuu 4/6/2023
好的,谢谢你的准确回答!
0赞 Narish 4/6/2023 #3

其他答案很好地解释了使用 .+

只是想标记一下,就像在 C/C++ 中一样,还有整数类型,所有类型都有无符号版本。当然,两者都有相同的担忧,即在对他们进行糟糕的操作时进行包装

下面的代码片段只是一个笑话,不要杀我,但这里有一个扩展方法,可以检查数值类型是否为正数,而不会有更改原始值或键入的风险

public static class NumericExtensions<T> where T : struct
{
    public static bool IsPositive(this T num) =>
        num switch  
        {  
            num is uint _ => true,
            num is int i => i > 0,
            num is ulong _ => true,
            num is long l => l > 0,
            num is double d => d > 0,
            num is float f => f > 0,
            num is decimal m => m > 0m
            //... add remaining numeric types
            _ => false //or throw exception
        };
}