另一个"使用未分配的局部变量'无论''问题

Pet*_*ter 4 c# compiler-errors language-design

这是我一段时间以来一直想知道的事情.我在标题中浏览了一系列包含错误的问题,但找不到解释此案例的问题.

首先看一下这个例子:

private void test() {
    string errorMessage;
    bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
    if (!isOK)
        throw new BusinessException(errorMessage ?? "Some error occured.");
}
Run Code Online (Sandbox Code Playgroud)

如果你编译它,编译器会抱怨这条消息:

错误2使用未分配的局部变量'errorMessage'

更改变量初始值设定项null将使其消失.

这将编译:

private void test() {
    string errorMessage = null;
    bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
    if (!isOK)
        throw new BusinessException(errorMessage ?? "Some error occured.");
}
Run Code Online (Sandbox Code Playgroud)

那么为什么我们得到编译错误?

Mar*_*ell 14

当您传递给它时VerifySomeStuff,您正在指定ref但它还没有值.这是不合法的,因为VerifySomeStuff可以选择读取值,此时此值没有定义的值.分配null满足明确的分配要求.另一种选择是out:

string errorMessage;
bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(id, out errorMessage);
if (!isOK)
    throw new BusinessException(errorMessage ?? "Some error occured.");
Run Code Online (Sandbox Code Playgroud)

这是合法的(但需要更改VerifySomeStuff,因为必须更改签名,现在需要在退出之前为参数赋值(除非发生异常)).从显示的代码中,如果没有错误,您可以选择VerifySomeStuff分配null给参数.

当然,如果bool和string然后复制 "有问题"的目的,你也可以使用:

string errorMessage = SomeClassWithBusinessRules.VerifySomeStuff(id);
bool isOK = errorMessage == null;
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 13

您收到编译错误,因为ref必须事先明确指定用作参数的变量.如果你改变方法来改为使用out参数,那就没关系了:

bool isOK = SomeClass.VerifySomeStuff(id, out errorMessage);
Run Code Online (Sandbox Code Playgroud)

请注意,这也需要更改VerifySomeStuff,以使其成为out参数.然后,该方法必须在任何"正常"返回路径中明确地分配值 - 以便在方法正常返回时,errorMessage明确分配.

分别参见10.6.1.2和10.6.1.3的细节refout参数.


Dav*_*nan 6

你是路过errorMessageref.这有进/出语义.换句话说,协议是接收者可以期望对象已经初始化,而您没有这样做.

好像你只是想要out语义.更改VerifySomeStuff使用out,而不是referrorMessage,也改变调用代码使用out.

请注意,在传递使用时out,在初始化对象之前,不允许被调用者读取.被调用者还有责任在返回之前执行该初始化.


Hen*_*man 5

您还可以通过将方法更改为更正"错误"

 SomeClassWithBusinessRules.VerifySomeStuff(int idOfStuffToVerify, 
            out string  errorMessage);
Run Code Online (Sandbox Code Playgroud)

当您使用out负载转移到方法时,除非您对errorMessage参数进行赋值,否则它将无法编译.