C# IsNullOrZero - c#

This pattern comes up very frequently in my code:
x= x== 0? 1: x;
//or
x= x==null? 1: x;
However it happens that sometimes x is a long expression and I'd have to use intermediate variables. That's just useless boilerplate code. I can cook up a method and call it instead:
Util.IfNullOrZero(x, 1);
But that's just ugly. What is the best way of expressing the pattern? In ruby there is such syntax for when x is nil which gets rid of redundant x's:
x||= 1
I could extend object in a manner
public static class wtf
{
public static T Default<T>(this object o, T d)
{
return o == null ? d : new object[] { o }.Cast<T>().First();
}
}
And then do
object param= null;
int x= param.Default(1);
But that's a bit expensive.
In short how to best make C# do x||= 1 like in ruby?
Update
This is what I cooked up. I'm currently looking for a faster way of using the Template parameter to convert object to T.
public static class MyExtensions
{
public static T d<T>(this object o, T d)
{
return o == null || o.Equals(default(T)) ? d : new object[] { o }.Cast<T>().First();
}
}
In fact the code does three things at once: Casts to default type, checks for default value and also checks for null.
Update 2
return o == null || o.Equals(default(T)) ? d : (T)o; // much simpler and faster
I still think it is a commonality which needs to be included in core language.
Update 3
This is what I finally wrote, taking into account DataTable DBNull types.
public static T d<T>(this object o, T d)
{
return o == null || (o is System.DBNull) || o.Equals(default(T)) ? d : (T)Convert.ChangeType(o, typeof(T));
}

For handling the "==null" case, the null coalesce operator does the trick.
y = x ?? z;
means
if (x == null)
y = z;
else
y = x;
I'm not aware of something that check for both zero and null, writing a method to perform this task might be the best solution. Here it goes:
public static T IsNullOrZero<T>(this T variable, T defaultValue)
{
// defaultValue can't be null, doesn't make sense
if (defaultValue == null) throw new ArgumentException("default value can't be null", "defaultValue");
if (variable == null || variable.Equals(default(T)))
return defaultValue;
return variable;
}
Usage:
x = x.IsNullOrZero(y);
Note: this in fact works on non-numbers too (name might be misleading if dealing with non-numbers... maybe something along the lines of IsNullOrDefault might be a better name).

You can check like
public static bool IsNullOrValue(this int? value, int valueToCheck)
{
return (value??valueToCheck) == valueToCheck;
}
more on here

For checking for null and providing a default value, you can use the ?? operator:
return x ?? new Foo();
That means, if x is null, return new Foo(), else return x. You can use it for reference types and nullable types. For nun-nullable types like int, you still need to explicitly check for 0.

What you want is the Coalesce operator (??), which does just that - if returns the first operand if it's not null, and the second if it is. This will instantiate a new object if the current one is null:
return myObj ?? new MyObject();
Note that the ?? operator works only for classes and reference types, not for ints and other value types that can't be null. There, you'll have to check manually for default, uninitialized values (0 for ints and shorts and stuff, false for bools, and so forth)

Related

Incorrect compiler error usage of uninitialized variable

I just encountered a case where Visual Studio tells me my code might result in accessing an uninitialized variable, but the rules of boolean logic dictate this isn't possible here.
I simplified the code to visualize the problem, in this case appearing for x:
static void Main(string[] args)
{
IDictionary<String, MyType> dictionary = null;
if (new Random().Next() % 2 == 0)
{
dictionary = new Dictionary<string, MyType>();
dictionary.Add("xyz", MyType.Whatever);
dictionary.Add("abc", MyType.DontCare);
}
var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;
}
enum MyType
{
None,
Whatever,
DontCare
}
In case dictionary isn't initialized it's null, thus resulting in ?? evaluating the ternary operator to false. This is the only case where x won't be initialized, but still I get the error message for x in the true case of the ternary operator.
Remarks: Setting parenthesis doesn't change anything, and resolving the ternary operator to a full-fledged if doesn't either.
Is this a known behavior or a bug?
EDIT: Just to clarify, I DO know how to fix the problem. I was just slightly surprised to encounter this error, since the described problem, accessing the uninitialized x, will never happen according to boolean logic.
EDIT: Using a full if doesn't change the problem:
static void Main(string[] args)
{
...
MyType myType;
if (dictionary?.TryGetValue("abc", out var x) ?? false)
{
myType = x; // <-- error still occurs here
}
else
{
myType = MyType.None;
}
}
The problem is the x in this line:
var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;
Since you have a null-propagation operator (?.), x will never be assigned when dictionary is null. You have to take out x as a separate variable above the var with a default value.
MyType x = MyType.None;
var myType = dictionary?.TryGetValue("abc", out x) ?? false ? x : MyType.None;
The static compiler just isn't smart enough to figure out the null-propagation operator will cause that expression always to return false (and hence x is never used). Not it just treats the statement as if it can.
As you can see on the C# language Github page, there is an active feature request to let the compiler figure out the outcome of the null-propagation operator.

obj Reference in C# and in vb

Public Function DBToID(ByVal strValue As Object) As Integer
If strValue Is DBNull.Value Then Return -1
If strValue = "-1" Then Return -1
Return CInteger(strValue)
End Function
I am trying to convert this code in C# and I did this
public static int DBToID(object strValue)
{
if (object.ReferenceEquals(strValue, DBNull.Value))
return -1;
if (object.ReferenceEquals(strValue,"-1"))
return -1;
return CInteger(strValue.ToString());
}
I just need to know whether I am doing it right or not as before I was doing
public static int DBToID(object strValue)
{
if (object.ReferenceEquals(strValue, DBNull.Value))
return -1;
if (strValue == "-1")
return -1;
return CInteger(strValue.ToString());
}
but it is saying Possible unintended reference comparison it is not giving any error just a green line under strValue=="-1".So please explain that object.referenceequals is correct or not .Thanks in advance
public int DBToID(object strValue)
{
if (strValue == DBNull.Value || Convert.ToString(strValue) == "-1")
return -1;
return Convert.ToInt32(strValue);
}
Try this
In C#, when the first operand of the == operator is cast as a reference-type (without any operator-overloading) then the == operator maps to the Object.ReferenceEquals operation. For the string-equality operation to be performed both operands must be known at compile-time to be String instances.
The most succinct (and safe) conversion would be this:
public Int32 DbToId(Object value) {
Int32 ret;
return value == DBNull.Value ? -1 :
Int32.TryParse( CultureInfo.InvariantCulture, value, out ret ) ? ret :
-1;
}
...which is a shorter form of this:
public Int32 DbToId(Object value) {
if( Object.ReferenceEquals( value, DBNull.Value ) ) return -1;
Int32 ret;
if( Int32.TryParse( CultureInfo.InvariantCulture, value, out ret ) ) return ret;
return -1; // fallback, base-case
}
Generally, try to avoid using VB.NET functions in C# (like CInteger) or the Convert.ToXXX methods as it is not immediately obvious what or how the conversion will work. Also avoid ToString calls with no arguments for the same reason. Prefer TryParse with appropriate IFormatInfo overloads.
When the == operator is used to compare two strings, the Equals method is called, which checks for the equality of the contents of the strings rather than the references themselves. For instance, "hello".Substring(0, 4)=="hell" is true, even though the references on the two sides of the operator are different (they refer to two different string objects, which both contain the same character sequence).
Note that operator overloading only works here if both sides of the operator are string expressions at compile time - operators aren't applied polymorphically. If either side of the operator is of type object as far as the compiler is concerned, the normal == operator will be applied, and simple reference equality will be tested.
Taken from here
The code you've written is not wrong per se. The linked post/snippet should help with any confusion for how strings work. Unless you know what you are doing explicitly, using ReferenceEquals is a bad idea and I would use one of the other by-value check methods.
If you call '.ToString()' on the object, then your second condition should work fine:
public int DBToID(object strValue)
{
if (strValue == DBNull.Value)
return -1;
if (strValue.ToString() == "-1")
return -1;
return System.Convert.ToInt32(strValue);
}

C# Safe navigation operator - what is actually going on?

I've been following the safe navigation operator feature added in C#6 with some interest. I've been looking forward to it for a while. But I'm finding some different behavior than I expected. I'm realizing I really don't understand how it actually works.
Given this class
class Foo {
public int? Measure;
}
Here's some code using the new operator.
Foo f = new Foo { Measure = 3 };
Console.WriteLine(f?.Measure); // 3
f = new Foo { Measure = null };
Console.WriteLine(f?.Measure); // null
f = null;
Console.WriteLine(f?.Measure); // null
Up to here, everything's working as expected. ?. is accessing members when the left hand side is not null, otherwise returning null. But here things go in a direction I wasn't expecting.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
What?
Why can I get HasValue from i, but not from the same expression I assigned to i? How can HasValue ever be null?
Edit: My real question is about program behavior, not a compilation error. I removed the extra stuff about compilation, and focused this question more narrowly on why two different results are returned by what seems like the same logic.
Let's walk through this logically.
var f = ???;
var i = f?.Measure;
var t = i.HasValue;
We don't know if f is null or not.
If f is null, then the result (i) is null
If f is not null, then the result (i) is an int
Therefore, i is defined as int?, and t is a bool
Now, let's walk through this:
var f = ???;
var i = f?.Measure.HasValue;
If f is null, then the result (i) is null
If f is not null, then the result (i) is Measure.HasValue, which is a bool.
Therefore, i is a bool?.
If f is null, we short-circuit and return null. If it's not, we return the bool result of .HasValue.
Essentially, when using ?. - the return type must be a reference value, or a Nullable<T>, as the expression can short circuit to return null.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
In this case, f is null.
The reason why i.HasValue returned false is because i is of type Nullable<int>. So even when the value of i is null, like in this case, i.HasValue is still accessible.
However, f?.Measure.HasValue immediately returns null after f? is evaluated. Hence the result you see above.
Just to quote Rob's comment:
The main thing to realise is that you're reading and understanding
this: f?.Measure.HasValue as this: (f?.Measure).HasValue, which it's
not.
Nullable<T> is actually a struct and therefore cannot be null, only its Value can, so HasValue will always be accessible.
I ran into this today.
What does the following C# snippet print?
public class NullTests
{
public static void Main(string[] args)
{
object obj = DoIt();
Console.WriteLine(obj?.ToString().NullToNothing());
}
private static object DoIt() => null;
}
public static class Extensions
{
public static string NullToNothing(this string input) => input ?? "nothing";
}
Answer: null.
What does the following Kotlin snippet print?
fun main() {
val obj = doIt()
println(obj?.toString().NullToNothing())
}
fun doIt() = null
fun String?.NullToNothing() = this ?: "nothing"
Answer: "nothing".
Like you, I was expecting the Kotlin behaviour, and it tripped me up for the better part of the day. :(

Bewildered by Enumerable Min and Max extension methods behavior with uninitialized nullable types

could someone shed some light (or freely speculate) why the Linq Min and Max extension methods behave the way they do when dealing with uninitialized nullable types ?
Perhaps the easiest way is show what I have observed :
int? a = null;
int? b = 1;
Nullable.Compare(a, b); // -1, indicating null is smaller then 1
new int?[] { null, 1 }.OrderBy(x => x).First(); // null, null smaller then 1
new[] { 0, 1 }.Min(); // 0 as expected
new int[] { }.Min(); // invalidoperator exception as expected
So far so good, but then ...
new int?[] { null, 1 }.Max(); // 1 as expected
new int?[] { null, 1 }.Min(); // 1 ?????, why not null ?
new int?[] { null, null }.Min(); // null, why null now and not above ?
new int?[] { }.Min(); // null, and no exception ???
I admit, I don't particularly care for Nullable types in the first place, but that's another story :-)
I do remain curious though about why it is implemented this way...
Cheers,
Bart
You can decompile the Nullable source code, which results in this definition:
public static int Compare<T>(Nullable<T> n1, Nullable<T> n2) where T : struct
{
if (n1.HasValue) {
if (n2.HasValue) return Comparer<T>.Default.Compare(n1.value, n2.value);
return 1;
}
if (n2.HasValue) return -1;
return 0;
}
It looks like the nullable.compare method intentionally returns a -1 in the case of n1 being null and n2 having a value.
Likewise you can decompile the linq source code, which results in this definition:
public static int? Min(this IEnumerable<int?> source) {
if (source == null) throw Error.ArgumentNull("source");
int? value = null;
foreach (int? x in source) {
if (value == null || x < value)
value = x;
}
return value;
}
The iteration over the source object checks if the value is null, and if it is, assigns the x to value*. It's just the default implementation of linq to return a number as the min value during a comparison against null.
As to the question why it does that, I assume it's because null represents the absence of a value rather than an integral value, and they (the guys who wrote linq) disagreed with the way comparable was originally built. They probably found no normal execution path where null would be considered the best answer to "what is the minimum value of this list of nulls and ints".

Built in CastOrDefault?

I get the feeling there is something built in for this. If object is null i'd like the default value (or specifically 0 and I am only using decimal/int). Is there a built in way to write this function?
static int GetDecimalFromObject(object o){
return o==null?0:(decimal)o;
}
Convert.ToDecimal and Convert.ToInt32 will return zero if passed null.
Try to use Convert.ToDecimal()
A decimal number that is equivalent to value, or 0 (zero) if value is
null.
Try like this;
static decimal GetDecimalFromObject(object o)
{
return o == null ? Convert.ToDecimal(0) : Convert.ToDecimal(o);
}
or more efficient;
static decimal GetDecimalFromObject(object o)
{
return Convert.ToDecimal(o);
}
Firstly, the decimal and int data types can't be null, so they would be 0 by default.
If you have a nullable decimal (decimal?) use the HasValue method to check if it is null then assign your default of 0.
The ?? Operator might help, but you have to provide the default value:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
Just to offer a different solution:
static int GetDecimalFromObject(object o)
{
return o as int? ?? 0;
}
Generic version:
static T GetValueFromObject<T>(object o) where T : struct
{
return o as T? ?? default(T);
}
Note that I've used the as operator. If you prefer to throw an exception in case o is not of the right type, use the cast operator.

Categories

Resources