Resharper warning - c#

Resharper gives a warning value assigned is not used in any execution path
private string FindMyId(string user, string defId) =>
defId = string.IsNullOrEmpty(defId) ? "defaultvalue" : defId;
I created above method to check if a value is empty and assign a default value to it anf return value in the same variable.It works functionaly. But it gives a message from resharper.

"value assigned is not used in any execution path"
Well, yeah. You reassign the parameter variable defId, but because there is only one statement in the method, there's no later method statement to read that saved value. In addition, because the defId parameter is not pass by ref, that change is only scoped to the method itself.
To get rid of the warning, just remove the variable assignment.
private string FindMyId(string defId) =>
string.IsNullOrEmpty(defId) ? "defaultvalue" : defId;
As posted, there's no use for the user parameter, and the method name FindMyId doesn't make logical sense for what the method is doing.

Related

Return value of method is modifying an object passed as a method parameter

I'm in a situation where I am writing a method where the return value directly modifies a class which was used to supply paramaters to the method.
Computer.MatchingPassword = PasswordFinder.Find(Computer.Name, PasswordList)
Does assigning to a property of a passed parameter like this have any hazards?
Technically, your code sample doesn't assign to the parameter, since you passed a property of the Computer object.
In other words, you only gave the function "name", so assigning to a different property of the same object would have no effect.
Now, in the more general case, you are still safe. Even passing the whole object, by the time you assign the return value the method has already completed. Any changes you make won't do anything.
In other words, the following code is functionally equivalent:
string password = PasswordFinder.Find(Computer.Name, PasswordList);
Computer.MatchingPassword = password;
Clearly no problems there. This is true even if it was passed by ref, as again, the method is totally done with the object, so any changes to it won't matter.

Force function to return value and make compile error C#

I have a class and a method within that class. However this class method returns a string. When I call the class method I don't get an error even though I'm not catching the string value return. Is there a way that I can make C# and .net force me to capture the value when returning a value.
Here is an example of what I mean.
1- create a class test.
class test
{
public string mystring() {
return "BLAH";
}
}
2- call the class method from program or another class
test mystring = new test();
mystring.mystring();
My compiler while working in Visual Studio does not complain that I'm not capturing the return value.
Is this normal or I'm missing something. Can I force the compiler to notify me that the function returns a value but I'm not catching it?
Thanks in advance for any suggestions you may have.
You could convert this to a property instead of a method:
public string myString
{
get
{
return "Blah";
}
}
Then you can't compile if you simply call the property:
myString.myString; //Results in "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement" Error
In a word, no. Not by force as such.
It's commonplace to not capture return values. Examples in the core libs abound (adding elements to a Hashset<T> for example, the function actually returns a bool to flag whether it was actually added or if it already existed - depending on individual implementation I may or may not care about that).
Of course, you can always just do something like string str = MyFunction() each time then never use str but I guess you probably already knew that.
You can try turning on warnings as errors by right-clicking the project in solution explorer, clicking Properties, going to the Build tab and setting Treat warnings as errors to all. This will force you to resolve all warnings before you can build and will capture some of the you-didn't-assign-this scenarios.
The compiler can't know that the only purpose of your method is to return the string or if it does some work that affects state, and so it can't complain when you don't assign the result to anything.
You can, however, set it up as a get only property per MikeH's answer. This will complain when you don't assign it to anything.
If your function has side effects then your should create unused variable and catch value. Compiler on release options delete this variable.
But if you don't have side effects in function: you may use visual studio tools such as "Watch window" and "Immediate window"
For some future person who comes across this issue, you can use an 'out'. This will force you to always assign the variable.
public void mystring(out returnString) {
returnString = "BLAH";
}
...
string OutString;
test mystring = new test();
mystring.mystring(out OutString);

TryGetValue - pass uninititialized value OK?

Take the following code for exhibit A:
string sql;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
Documentation for Dictionary says that if the Key isn't found, the reference type will be set to null. OK, that's fine.
If the key is found, how is the variable 'sql' filled?
Is the found value for the key cloned?
Is a type of object for the item found created and then the contents of the object copied?
Is this safe?
Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:
var sql = string.Empty;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
Then the variable 'sql' is initialized and a safe place for the object exists.
(My question comes from my aversion of null pointers in my C programming days.)
In my view, it's better not to set it to a value. After all, that value is guaranteed to be replaced by the method call (assuming that doesn't throw an exception) so why bother specifying a value which is pointless? It just misleads the reader into thinking it makes a difference.
An out parameter is special in that the variable you use to provide a value for it doesn't have to be definitely-assigned before the call, but will be definitely-assigned after the call. Any value it has before the call will not be visible to the method.
(Note that ref parameters don't behave that way - they have to be definitely assigned beforehand.)
See my article on C# argument passing for more details on the different parameter modes in C#.
If the key is found, how is the variable 'sql' filled? Is the found value for the key cloned? Is a type of object for the item found created and then the contents of the object copied?
The value of the parameter within the method becomes the value of the variable in the callers code, in the same way as normal assignment. There is no object cloning going on.
If the key is found, how is the variable 'sql' filled?
You can think it like this:
var sql = GetQueries[type.TypeHandle];
Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:
No actually it doesn't matter. You don't have to initialize sql to a value, since you are passing it as out argument.The function guarantees that it will set the value of it's argument by declaring it as out.

Why can't an out parameter have a default value?

Currently when trying to do something in a method that takes an out parameter, I need to assign the value of the out parameter in the method body, e.g.
public static void TryDoSomething(int value, out bool itWorkerd)
{
itWorkerd = true;
if (someFavourableCondition)
{
// if I didn't assign itWorked variable before this point,
// I get an error: "Parameter itWorked must be assigned upon exit.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
I'd like to be able to set a default value of the itWorked parameter so I don't have to arbitrarily set the value in the body of the method.
public static void TryDoSomething(int value, out bool itWorkerd = true)
{
if (someFavourableCondition)
{
// itWorked was already assigned with a default value
// so no compile errors.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
Why is it not possible to assign a default value for an out parameter?
Default values are available for parameters passed by value. The parameter is still passed to the function but if the code omits the parameter, the compiler supplies the missing value.
Your proposed feature is quite different. Instead of the caller omitting to pass the value, you propose to allow the implementer of the function to omit setting the value. So, this is a quite different feature. Why was it not implemented? Here are some possible reasons:
Nobody thought to implement this feature.
The designers considered the feature and rejected it as not useful enough to be worth the cost of implementing.
The designers considered the feature and rejected it as being confusing because it uses similar syntax to default value parameters, but has a quite different meaning.
I appreciate this isn't exactly answering the original question, but I'm unable to contribute to the comments. I had the same question myself so found myself here.
Since C#7 now allows out parameters to effectively be variable declarations in the calling scope, assigning a default value would be useful.
Consider the following simple method:
private void ResolveStatusName(string statusName, out string statusCode)
{
statusCode = "";
if (statusName != "Any")
{
statusCode = statusName.Length > 1
? statusName.Substring(0, 1)
: statusName;
}
}
It felt intuitive to modify it like so:
private void ResolveStatusName(string statusName, out string statusCode = "")
{
if (statusName != "Any")
{
statusCode = statusName.Length > 1
? statusName.Substring(0, 1)
: statusName;
}
}
The intention was to not only declare the statusCode value, but also define it's default value, but the compiler does not allow it.
Even if it allowed you to give a default value like that, it would still require you to assign value for the parameter for all returns. So your default value will be overridden.
Default parameter values are the default value for parameters passed in to the method. You have to specify a variable to pass for an out parameter so that you can get the returned value.
Your first example, in a way, has a default, set at the beginning of the method.
The out method parameter keyword on a method parameter causes a method to refer to the same variable that was passed into the method. Any changes made to the parameter in the method will be reflected in that variable when control passes back to the calling method.
Declaring an out method is useful when you want a method to return multiple values. A method that uses an out parameter can still return a value. A method can have more than one out parameter.
To use an out parameter, the argument must explicitly be passed to the method as an out argument. The value of an out argument will not be passed to the out parameter.
A variable passed as an out argument need not be initialized. However, the out parameter must be assigned a value before the method returns.
Compiler will not allow you to use out parameter as default parameter because it is violating its use case. if you don't pass it to function you cannot use its value at calling function.
if you could call below function like TryDoSomething(123) then there is no use of out parameter because you will not be able to use value of itWorked
public static void TryDoSomething(int value, out bool itWorkerd = true)
{
if (someFavourableCondition)
{
// itWorked was already assigned with a default value
// so no compile errors.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
If you have two calls to a method that uses 'out' or 'ref', and you want to avoid to split the method up in two, if one of the calls is not using these parameters, an elegant solution to avoid the warning from the compiler that "the value is not being used" (or something similar), is to use something like this:
method("hi", out _);
A method parameter declared with 'out' cannot have its value assigned by the caller. So a default value cannot be assigned during the call, either.
Also, you must always initialize an 'out' parameter in the method's body before using the parameter or returning from the method. This would overwrite any default value.
This is the whole point with the 'out' modifier. If you want a different behavior, check out the 'ref' and 'in' modifiers.

What should the out value be set to with an unsuccessfull TryXX() method?

I'm implementing a TryParse(string s, Out object result) method.
If the parse fails, I would like not to touch the out parameter so any previous result will remain intact.
But VS2k8 won't let me. I have to set the value of the out object no matter what.
Should I just put result = result for the sake of pleasing the compiler? Am I missing something?
Assign null (or default(T) more generally). You must assign a value, that's what 'out' means.
Your suggestion of result = result won't work, because it's an out parameter - it's not definitely assigned to start with, so you can't read its value until you've assigned a value to it.
result = null;
is definitely the right way to go for an object out parameter. Basically use default(T) for whatever type T you've got. (The default operator is useful in generic methods - for non-generic code I'd normally just use null, 0, whatever.)
EDIT: Based on the comment from Boris, it may be worth elaborating on the difference between a ref parameter and an out parameter:
Out parameters
Don't have to be definitely assigned by the caller
Are treated as "not definitely assigned" at the start of the method (you can't read the value without assigning it first, just like a local variable)
Have to be definitely assigned (by the method) before the method terminates normally (i.e. before it returns; it can throw an exception without assigning a value to the parameter)
Ref parameters
Do have to be definitely assigned by the caller
Are treated as "definitely assigned" at the start of the method (so you can read the value without assigning it first)
Don't have to be assigned to within the method (i.e. you can leave the parameter with its original value)
result = null;
Just put some default value. For example the Int32.TryParse method puts zero.
You could use ref instead of out if you don't want to assign a value, although this must then be initialised by the caller.
You could throw an exception before the code that is supposed to set result.

Categories