相关疑难解决方法(0)

好奇的null-coalescing运算符自定义隐式转换行为

注意:这似乎已在Roslyn中修复

写我的回答时,此问题出现了这一个,其中谈到了的关联性空合并运算符.

提醒一下,null-coalescing运算符的概念就是表单的表达式

x ?? y
Run Code Online (Sandbox Code Playgroud)

首先评估x,然后:

  • 如果值为xnull,y则进行求值,这是表达式的最终结果
  • 如果值x是非空,y评估,的值x是表达的最终结果,转换到编译时间类型的后y如果需要的话

现在通常不需要转换,或者它只是从可空类型到非可空类型 - 通常类型相同,或者只是从(比如说)int?int.但是,您可以创建自己的隐式转换运算符,并在必要时使用它们.

对于简单的情况x ?? y,我没有看到任何奇怪的行为.但是,(x ?? y) ?? z我看到一些令人困惑的行为.

这是一个简短但完整的测试程序 - 结果在评论中:

using System;

public struct A
{
    public static implicit operator B(A input)
    {
        Console.WriteLine("A to B");
        return new B();
    }

    public static implicit operator …
Run Code Online (Sandbox Code Playgroud)

c# null-coalescing-operator

535
推荐指数
5
解决办法
2万
查看次数

null合并运算符的右关联如何表现?

null coalescing运算符是右关联的,表示表单的表达式

第一个?第二个 - 第三个

被评估为

第一个?(第二次 - 第三次)

基于上述规则,我认为以下翻译是不正确的.

从:

Address contact = user.ContactAddress;
if (contact == null)
{
    contact = order.ShippingAddress;
    if (contact == null)
    {
        contact = user.BillingAddress;
    }
}
Run Code Online (Sandbox Code Playgroud)

至:

Address contact = user.ContactAddress ??
                  order.ShippingAddress ??
                  user.BillingAddress;
Run Code Online (Sandbox Code Playgroud)

相反,我认为以下是正确的(如果我错了请纠正我)

Address contact = (user.ContactAddress ?? order.ShippingAddress) ??
                   user.BillingAddress;
Run Code Online (Sandbox Code Playgroud)

c#

29
推荐指数
3
解决办法
2498
查看次数

为什么本地函数并不总是隐藏在C#7中?

我在下面展示的是一个理论问题.但我对新的C#7编译器如何工作并解析本地函数感兴趣.

C#7中,我可以使用本地函数.例如(您可以在LinqPad beta中尝试这些示例):

示例1:嵌套Main()

void Main()
{
    void Main()
    {
        Console.WriteLine("Hello!");
    }
    Main();
}
Run Code Online (Sandbox Code Playgroud)

而不Main()是以递归方式调用,本地函数Main()被调用一次,因此它的输出是:

你好!

编译器接受此操作时没有警告和错误.

示例2: 在这里,我更深入一级,如:

void Main()
{
    void Main()
    {
        void MainL()
        {
            Console.WriteLine("Hello!");
        }
        MainL();
    }
    Main();     
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我也期望相同的输出,因为最里面的本地函数被调用,然后一个级别,Main()只是另一个具有局部范围的本地函数,所以它应该与第一个示例没有太大的不同.

但令我惊讶的是,我收到了一个错误:

CS0136无法在此范围内声明名为"Main"的本地或参数,因为该名称用于封闭的本地范围以定义本地或参数


问题: 您能解释为什么在例2中发生此错误,但在示例1中没有?

我想,每个内部Main()都有一个局部范围,并隐藏在外面.


更新: 感谢所有到目前为止已经提出建议的人(无论是答案还是评论),你为了解C#编译器的行为而写的是非常值得的.

根据我的阅读,在考虑了可能性之后,我在你的帮助下发现它可能是编译器错误或设计行为.

回想一下,C#有一些设计目标,可以将它与C++等语言区分开来.

如果你对我所做的事情有兴趣进一步研究它:我已经将最里面的函数重命名为MainL:

例2b:

IL_0000:  call        UserQuery.<Main>g__Main0_0
IL_0005:  ret         

<Main>g__Main0_0:
IL_0000:  call        UserQuery.<Main>g__Main0_1
IL_0005:  ret         

<Main>g__Main0_1:
IL_0000:  ldstr       "Hello!"
IL_0005:  call        System.Console.WriteLine
IL_000A: …
Run Code Online (Sandbox Code Playgroud)

c# scope nested function c#-7.0

20
推荐指数
3
解决办法
1004
查看次数

为什么在C#7中使用TryParse语法(空出参数)如果编译它会发出警告?

在C#7中,你被允许这样做

            if (int.TryParse("123", out int result)) 
                Console.WriteLine($"Parsed: {result}");
Run Code Online (Sandbox Code Playgroud)

或者 - 如果您不使用结果并且只想检查解析是否成功,则丢弃out值:

           if (int.TryParse("123", out _))
                Console.WriteLine("Syntax OK");                
Run Code Online (Sandbox Code Playgroud)

这通常很好,但在Visual Studio 2017中,out参数为空的第二个示例生成警告

警告AD0001:Analyzer'Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CSharpSimplifyTypeNamesDiagnosticAnalyzer'抛出了类型为'System.NullReferenceException'的异常,并显示消息'对象引用未设置为对象的实例.'.

我可以验证它发生的Visual Studio版本是

Visual Studio Enterprise 2017版本15.1(26403.7)发布
Visual Studio Enterprise 2017版本15.2(26430.4)发行版

这是一个错误,还是使用int.TryParse("123", out _)不正式支持?到目前为止我找不到任何暗示.


为了完整起见,这是显示问题的控制台应用程序的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            if (int.TryParse("123", out _))
                Console.WriteLine("Syntax OK");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

c# c#-7.0 visual-studio-2017

18
推荐指数
1
解决办法
1201
查看次数