How to tell if an out parameter was set already? - c#

Is there a way to know if an out parameter was set already or not. This is the pseudocode for what I am looking for:
public virtual string blabla(long num, out bool bval)
{
if (!bval.HasValue)
{
//Do some default logic
bval = defaultValue;
}
return blabla2(num, bval);
}

You can't - you can't read the variable until it's been definitely assigned within your method. You should think of it as being like a local variable, declared but not assigned any value at the start of the method - but which you must assign a value to before you return. (It's okay not to have assigned a value to it if an exception is thrown.)
If you want a parameter which carries information as input to the method as well as propagating information out, you should use ref instead of out.
See my article on parameter passing for more information.

In addition to Jon's excellent answer, if you want the parameter to still be out, but need to see if it has been assigned a value at some place inside the method, you could use a local nullable type like follows:
public virtual string blabla(long num, out bool bval)
{
bool? bvalLocal;
... //I'm assuming there is some code here that may or
//may not assign bvalLocal?
// This whole if block may not be needed if the default
// value is the default for the type (i.e. false) as
// GetValueOrDefualt() will take care of that (see
// second to last line).
if (!bvalLocal.HasValue)
{
//Do some default logic
bvalLocal = defaultValue;
}
bval = bvalLocal.GetValueOrDefault();
return blabla2(num, bval);
}

Related

What does "is { }" mean?

I see the following code sometimes, and have no idea what the expression is actually testing.
public static void Something(string[] value)
{
if (value is { })
{
DoSomethingElse();
}
}
That's just the empty property pattern in C# 8, meaning the value not null. It matches any value type or reference type. As Panagiotis Kanavos notes in the comments, this is equivalent to the good old value is object check which has been in C# for a long time.
Generally if you were to specify a property, then it would match or not. This esoteric example illustrates that:
if (value is { Length: 2 })
{
// matches any object that isn't `null` and has a property set to a length of 2
}
The property patterns work best and are most clear when comparing with other patterns in cases such as switch expressions.
While Daniel's answer is right, I think it might be useful to add some context about why you may see the empty property pattern in use. Consider this example controller method that needs some validation done:
public async Task<IActionResult> Update(string id, ...)
{
if (ValidateId(id) is { } invalid)
return invalid;
...
}
In the above, ValidateId() could return null or an instance of BadObjectRequestResult. If the former is returned, the validation is successful and moves on to the rest of the body of Update. If the latter is returned, is {} is true (i.e. of course an instance of BadObjectRequestResult is an object), and the validation fails.
Nicely, out of this we've also provided a variable name, invalid, which we can return immediately. Without that we'd need slightly more verbose code.
public async Task<IActionResult> Update(string id, ...)
{
var invalid = ValidateId(id);
if (invalid != null)
return invalid;
...
}
Whether one is more readable or the other is up to the reader, I've just presented one way the empty property pattern can be used.

Value Assigned Is Not Used

I may be overlooking something, well obviously I am. I am using an uninitialized variable of type int (carRequired). I am utilizing this variable inside an IF statement (code below). However, I get a warning stating the variable is never used yet it is. Yes, I am aware of not being good practice to embed sql, however I am told to do it this way for now.
public bool UpdateDiscrepancyReport()
{
var errorStatus = false;
int carRequired ;
carRequired = cbxCarRequired.Checked == false ? 0 : 1;
var updateQuery = "my query string ";
dbf.OpenConnection(updateQuery);
bool updateStatus = dbf.OpenConnection(updateQuery);
if (updateStatus)
{
errorStatus = true;
}
else
{
MessageBox.Show(#"Error in updating DR" + tbxDRNumber.Text+#" ",#"Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return errorStatus;
}
The variable is never used. It is assigned to, but the variable is never used after that assignment; you don't do anything after assigning the result of the ternary operation to it. In fact, the variable isn't necessary at all, and neither is errorStatus (in the original code you posted), since you never do anything in the code that will change it's value after it is initialized.
The code you've posted (prior to your edit that added several more lines) is the exact equivalent of
public bool UpdateDiscrepancyReport()
{
dbf.OpenConnection(updateQuery);
return false;
}
The compiler is telling you that the variable declaration and assignment to carRequired is meaningless, because it does not affect anything in your code. Determining whether the checkbox is checked or not only has meaning if your code does something differently based on that information, and the use of carRequired as written does nothing based on the value assigned; therefore, the assignment (and variable declaration) are useless.

How can I get the default value of a field in a class in C#?

Say I have my class, and I have the non-static variable
int x = 5;
After the code runs x is changed to something else, how can I get the value x started with using reflection?
Short answer: you can't.
If you implement some kind of custom transactional system, than it is possible. Out of the box: no luck.
And yes, the custom transactional system can be very simple: add another field or property that you use to 'remember' the initial value.
if i understand you correctly you want the initial value of the x.
for that you need another member or parameter to keep the first initializing of x. for example in your class:
int FirstX = -1;// or any other value you know ain't gonna come
bool firstInitial = true;
public int X
{
set
{
if(firstInitial)
{
FirstX = value;
firstInitial = false;
}
x = value
}
}
Now if you mean default value that is set at class level, you already know as it is constant other way would be creating an instance of the class for which you need default value.
ClassName className= new ClassName();
className.MyProp//This will always give default value.
new ClassName().MyProp //would also do.
If you want list of transactional values you need to implement it, reflection is not meant for that.

Question about compilation error related to a use in the keyword/reserved word "out"

Hello
I'm having an error with this code:
"The out parameter 'o_BlockingSquaresArr' must be assigned to before control leaves the current method"
Now this error paints each return statement of each method apart from the last one with red..
I don't understand what is the problem regarding my specific code
Please help me,
Thanks in Advance
internal bool isLegalMove(Square i_Move, out List<Square> o_BlockingSquaresArr)
{
bool result;
if (m_GameBoard[i_Move.RowIndex, (int)i_Move.ColIndex].Coin != null)
{
result = false;
m_MessageBuffer = "You have enterd a square which is already
occupied, please try again...";
m_ErrorFlag=true;
}
else
{
result = checkIfThereIsAtLeastOneSeqInOneDirection(i_Move,out o_BlockingSquaresArr);
}
return result;
}
internal bool checkIfThereIsAtLeastOneSeqInOneDirection(Square i_Move, out List<Square> o_BlockingSquaresArr)
{
const int k_EightDirections = 8;
bool isSequenceFound, finalRes = false;
for (int i = 1; i <= k_EightDirections; i++)
{
isSequenceFound = checkOpponentSequenceInDirection(i_Move, (eDirections)i, out o_BlockingSquaresArr);
if (isSequenceFound)
{
finalRes = true;
}
}
return finalRes;
}
internal bool checkOpponentSequenceInDirection(Square i_Move, eDirections i_Direction, out List<Square> o_BlockingSquaresArr)
{
//I've shortened this code only relevant things
Square o_AdjacentSquare = new Square();
adjacentCoin = doSwitchAndRetrieveAdjacentCoin(i_Move, i_Direction, out o_AdjacentSquare);
// ...
if (isThereAnOpponentSequence)
{
o_BlockingSquaresArr.Add(o_AdjacentSquare);
}
return isThereAnOpponentSequence;
}
As the compiler error says, an out parameter has to be definitely assigned before any non-exceptional return of a method. I can't see any assignment to o_BlockingSquaresArr anywhere. Why are you even declaring it as an out parameter to start with?
An out parameter must be assigned a value before the method returns. In your isLegalMove method, o_BlockingSquaresArr is only assigned in the else block, so the compiler detects there are some cases where it is not initialized. You must make sure that all code paths in the method assign a value to o_BlockingSquaresArr before returning
You need to assign something to the out parameter in every execution path. In your case, you forget that in one case. Simply assign a default value of the beginning of the method so you don't run into it.
I can't tell you where as you didn't include the method name it is happening in.
In the IsLegalMove function, you need to assign a value to the o_BlockingSquaresArr variable
You need to assign something to out parameters in every (normally terminating) codepath. And you don't do that.
For example in some functions you only assign to the parameter inside the for-loop. And if the loop has 0 iterations this will never happen.

Setting the default value of a C# Optional Parameter

Whenever I attempt to set the default value of an optional parameter to something in a resource file, I get a compile-time error of
Default parameter value for 'message' must be a compile-time constant.
Is there any way that I can change how the resource files work to make this possible?
public void ValidationError(string fieldName,
string message = ValidationMessages.ContactNotFound)
In this, ValidationMessages is a resource file.
One option is to make the default value null and then populate that appropriately:
public void ValidationError(string fieldName, string message = null)
{
string realMessage = message ?? ValidationMessages.ContactNotFound;
...
}
Of course, this only works if you don't want to allow null as a genuine value.
Another potential option would be to have a pre-build step which created a file full of const strings based on the resources; you could then reference those consts. It would be fairly awkward though.
No, you will not be able to make the resource work directly in the default. What you need to do is set the default value to something like null and then do the resource lookup when the parameter has the default value in the body of the method.
Another option is to split your method into two, and have the one overload call the other, like so:
public void ValidationError(string fieldName)
{
ValidationError(fieldName, ValidationMessages.ContactNotFound);
}
public void ValidationError(string fieldName, string message)
{
...
}
This way also enables you to pass null as a value for message in case that is also a valid value for that parameter.

Categories