Another "Using an unrecognized local variable" independently "

This is what I wondered about for a while. I looked through a bunch of questions containing an error below in my title, but could not find the 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 about this message:

Error 2 Using the unassigned local variable 'errorMessage'

Changing the initializer of a variable to null will force it to leave.

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 a compilation error?

+4
source share
6 answers

When you pass it to VerifySomeStuff , you specify ref , but it doesn't matter yet. This is not legal, since VerifySomeStuff can choose to read a value that does not currently have a specific value. The null assignment satisfies a specific 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 now you need to assign a value before the parameter before exiting (unless an exception occurs)) From the code shown, you can select VerifySomeStuff to assign null parameter if there is no error .

Of course, if bool and string then duplicate the goal "was there a problem", you can also use:

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

You get a compilation error because the variable used as the ref argument must definitely be assigned in advance. If you change the method to use the out parameter, this will be fine:

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

Note that this also requires a change to VerifySomeStuff to make it an out parameter. Then this method would have to definitely assign a value in any "normal" return path, so that by the time the method returns, normally errorMessage definitely assigned.

For details on the ref and out parameters, see sections 10.6.1.2 and 10.6.1.3.

+13
source

You pass errorMessage on ref . It has in / out semantics. In other words, the protocol is that the receiver can expect the object to be initialized, which you did not do.

It seems you just want the semantics out . Modify VerifySomeStuff to use out instead of ref for errorMessage , and also change the calling code to use out .

Note that when transferring with out called call is not allowed to read until the object is initialized. The caller is also responsible for performing this initialization before returning.

+6
source

You can also fix the โ€œerrorโ€ by changing the method to

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

When you use out , the burden goes to the method; it will not compile unless you set the errorMessage parameter.

+5
source

When passing the ref argument, one of the things that the called code can cause is to redefine the variable of the ref argument to a new location, that is, update its link. For this to happen, the variable must point to something in the first place, so it must be assigned, even if it is just null .

+2
source

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

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

Since errorMessage is only required when an error occurs, why do you need an additional return value? You can shorten this to:

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

(Of course, then you no longer have a case with an โ€œerror.โ€ But displaying โ€œuselessโ€ error messages is bad practice.)

In fact, if the error is an exceptional circumstance (i.e., something that is not part of the regular control flow, but rather something that indicates a data or logic error), it makes 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); ... } } 
+2
source

Source: https://habr.com/ru/post/1369624/


All Articles