另一个“使用未分配的局部变量‘无论如何’” ”问题

发布于 2024-12-02 05:18:03 字数 787 浏览 1 评论 0原文

这是我想知道有一段时间的事情。我浏览了一堆标题中包含以下错误的问题,但找不到解释这种情况的问题。

首先看这个例子:

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 技术交流群。

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

发布评论

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

评论(6

梦纸 2024-12-09 05:18:03

当您将其传递给 VerifySomeStuff 时,您指定了 ref 但它还没有值。这是不合法的,因为 VerifySomeStuff 可以选择读取该值,但此时该值还没有定义的值。赋值null满足明确赋值的要求。另一种选择是 out

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

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

当然,如果布尔和字符串重复“是否有问题”目的,您也可以使用:

string errorMessage = SomeClassWithBusinessRules.VerifySomeStuff(id);
bool isOK = errorMessage == null;

When you pass it to VerifySomeStuff, you are specifying ref but it does not yet have a value. That is not legal, as VerifySomeStuff could choose to read the value, which does not have a defined value at this point. Assigning null satisfies the definite assignment requirement. An alternative would be out:

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

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 for VerifySomeStuff to assign null 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:

string errorMessage = SomeClassWithBusinessRules.VerifySomeStuff(id);
bool isOK = errorMessage == null;
青衫儰鉨ミ守葔 2024-12-09 05:18:03

您会收到编译错误,因为用作 ref 参数的变量必须事先明确分配。如果您将方法更改为使用 out 参数,那就没问题了:

bool isOK = SomeClass.VerifySomeStuff(id, out errorMessage);

请注意,这也需要更改 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 an out parameter instead, it'll be fine:

bool isOK = SomeClass.VerifySomeStuff(id, out errorMessage);

Note that this requires a change to VerifySomeStuff too, to make it an out 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 and out parameters respectively.

面如桃花 2024-12-09 05:18:03

您正在通过 ref 传递 errorMessage。这具有输入/输出语义。换句话说,该协议是接收者可以期望该对象已被初始化,而您没有这样做。

似乎您只是想要 out 语义。将 VerifySomeStuff 更改为对 errorMessage 使用 out 而不是 ref,并将调用代码更改为使用

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

You are passing errorMessage by ref. 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. Change VerifySomeStuff to use out rather than ref for errorMessage, and also change the calling code to use out.

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.

鹿! 2024-12-09 05:18:03

您还可以通过将方法更改为来更正“错误”。

 SomeClassWithBusinessRules.VerifySomeStuff(int idOfStuffToVerify, 
            out string  errorMessage);

当您使用 out 时,负担转移到该方法,除非您对 errorMessage 参数进行赋值,否则它将不会编译。

You can also correct the 'error' by changing the method to

 SomeClassWithBusinessRules.VerifySomeStuff(int idOfStuffToVerify, 
            out string  errorMessage);

When you use out the burden shifts to the method, it will not compile unless you make an assignment to the errorMessage parameter.

凉栀 2024-12-09 05:18:03

当传递ref参数时,被调用代码可以做的事情之一是将ref参数变量重新指向一个新位置,即更新其引用。为了实现这一点,变量必须首先指向某个东西,因此必须对其进行赋值,即使这只是 null

When passing a ref argument, one of the things the called code can do is re-point the ref 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 to null.

手心的温暖 2024-12-09 05:18:03

你的问题(为什么编译器抱怨)已经被其他人回答了。不过,我建议您重新考虑您的设计:

bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
if (!isOK)
    throw new BusinessException(errorMessage ?? "Some error occured.");
}

既然只有发生错误时才需要 errorMessage,为什么还需要额外的返回值呢?您可以将其缩短为:(

string error = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify);
if (error != null)
    throw new BusinessException(error);
}

当然,这样您就不会再遇到“发生了一些错误”的情况。但是显示“无用”的错误消息无论如何都是不好的做法。)

事实上,如果错误是异常的情况(即,不属于常规控制流的一部分,而是指示数据或逻辑错误的情况),将异常移至VerifySomeStuff内可能是有意义的:

// no return value
SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify);

class SomeClassWithBusinessRules {
    void VerifySomeStuff(int id) {
        ...
        if (someCondition)
            throw new BusinessException(error);
        ...
    }
}

Your question (why does the compiler complain) has already been answered by others. I would, however, suggest that you reconsider your design:

bool isOK = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify, ref errorMessage);
if (!isOK)
    throw new BusinessException(errorMessage ?? "Some error occured.");
}

Since errorMessage is only needed when an error occurs, why do you need the extra return value? You could shorten this to:

string error = SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify);
if (error != null)
    throw new BusinessException(error);
}

(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:

// no return value
SomeClassWithBusinessRules.VerifySomeStuff(idOfStuffToVerify);

class SomeClassWithBusinessRules {
    void VerifySomeStuff(int id) {
        ...
        if (someCondition)
            throw new BusinessException(error);
        ...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文