另一个“使用未分配的局部变量‘无论如何’” ”问题
这是我想知道有一段时间的事情。我浏览了一堆标题中包含以下错误的问题,但找不到解释这种情况的问题。
首先看这个例子:
private void test() {
string errorMessage;
bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
if (!isOK)
throw new BusinessException(errorMessage ?? "Some error occured.");
}
如果你编译这个例子,编译器会抱怨这个消息:
错误 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.");
}
那么为什么我们会收到编译错误呢?
This is something that I have wondered about for a while now. I have browsed a bunch of questions containing the error below in their title but couldn't find one that explains this case.
First look at this example:
private void test() {
string errorMessage;
bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
if (!isOK)
throw new BusinessException(errorMessage ?? "Some error occured.");
}
If you compile this the compiler will complain with this message:
Error 2 Use of unassigned local variable 'errorMessage'
Changing the variable initializer to null
will make it go away.
This will compile:
private void test() {
string errorMessage = null;
bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
if (!isOK)
throw new BusinessException(errorMessage ?? "Some error occured.");
}
So why do we get the compilation error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当您将其传递给
VerifySomeStuff
时,您指定了ref
但它还没有值。这是不合法的,因为VerifySomeStuff
可以选择读取该值,但此时该值还没有定义的值。赋值null
满足明确赋值的要求。另一种选择是out
:这是合法的(但需要更改
VerifySomeStuff
,因为必须更改签名,并且现在需要退出前给参数赋值(除非发生异常))。从显示的代码中,如果没有错误,您可以选择VerifySomeStuff
将null
分配给参数。当然,如果布尔和字符串重复“是否有问题”目的,您也可以使用:
When you pass it to
VerifySomeStuff
, you are specifyingref
but it does not yet have a value. That is not legal, asVerifySomeStuff
could choose to read the value, which does not have a defined value at this point. Assigningnull
satisfies the definite assignment requirement. An alternative would beout
:which would be legal (but requires changes to
VerifySomeStuff
, since the signature must be changed and it is now required to assign a value to the parameter before exit (unless an exception occurs)). From the code shown, it you might choose forVerifySomeStuff
to assignnull
to the parameter if there is no error.Of course, if the bool and string then duplicate the "was there a problem" purpose, you could also use:
您会收到编译错误,因为用作
ref
参数的变量必须事先明确分配。如果您将方法更改为使用out
参数,那就没问题了:请注意,这也需要更改
VerifySomeStuff
,使其成为out
参数。然后,该方法必须在任何“正常”返回路径中明确分配一个值 - 这样,当该方法正常返回时,errorMessage
已明确分配。分别参见第 10.6.1.2 节和第 10.6.1.3 节 ref 和 out 参数的详细信息。
You get the compilation error because a variable used as a
ref
argument has to be definitely assigned beforehand. If you change the method to use anout
parameter instead, it'll be fine:Note that this requires a change to
VerifySomeStuff
too, to make it anout
parameter. The method would then have to definitely assign a value in any "normal" return path - so that by the time the method returns normally,errorMessage
is definitely assigned.See sections 10.6.1.2 and 10.6.1.3 details of
ref
andout
parameters respectively.您正在通过
ref
传递errorMessage
。这具有输入/输出语义。换句话说,该协议是接收者可以期望该对象已被初始化,而您没有这样做。似乎您只是想要
out
语义。将VerifySomeStuff
更改为对errorMessage
使用out
而不是ref
,并将调用代码更改为使用出
。请注意,当您使用
out
传递时,被调用者在对象初始化之前不允许读取。被调用者还有责任在返回之前执行初始化。You are passing
errorMessage
byref
. This has in/out semantics. In other words, the protocol is that recipient can expect the object to have been initialised, which you did not do.It seems as though you simply want
out
semantics. ChangeVerifySomeStuff
to useout
rather thanref
forerrorMessage
, and also change the calling code to useout
.Note that when you pass using
out
, the callee is not allowed to read until the object has been initialized. The callee also has the responsibility of performing that inialization before returning.您还可以通过将方法更改为来更正“错误”。
当您使用
out
时,负担转移到该方法,除非您对 errorMessage 参数进行赋值,否则它将不会编译。You can also correct the 'error' by changing the method to
When you use
out
the burden shifts to the method, it will not compile unless you make an assignment to the errorMessage parameter.当传递
ref
参数时,被调用代码可以做的事情之一是将ref
参数变量重新指向一个新位置,即更新其引用。为了实现这一点,变量必须首先指向某个东西,因此必须对其进行赋值,即使这只是null
。When passing a
ref
argument, one of the things the called code can do is re-point theref
argument variable to a new location i.e. update its reference. In order for this to happen, the variable must point to something in the first place, therefore it must be assigned, even if this is just tonull
.你的问题(为什么编译器抱怨)已经被其他人回答了。不过,我建议您重新考虑您的设计:
既然只有发生错误时才需要
errorMessage
,为什么还需要额外的返回值呢?您可以将其缩短为:(当然,这样您就不会再遇到“发生了一些错误”的情况。但是显示“无用”的错误消息无论如何都是不好的做法。)
事实上,如果错误是异常的情况(即,不属于常规控制流的一部分,而是指示数据或逻辑错误的情况),将异常移至VerifySomeStuff内可能是有意义的:
Your question (why does the compiler complain) has already been answered by others. I would, however, suggest that you reconsider your design:
Since
errorMessage
is only needed when an error occurs, why do you need the extra return value? You could shorten this to:(Of course, then you don't have the "Some error occured" case anymore. But showing "useless" error messages is bad practice anyway.)
In fact, if the error is an exceptional circumstance (i.e., something that's not part of the regular control flow but rather something indicating a data or logic error), it might make sense to move the exception inside VerifySomeStuff: