Built in CastOrDefault? - c#

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.

Related

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);
}

Static members of nullable types

In c# a value-type cannot have a value of null, however you can enable this by appending a question mark.
e.g.
int intCannotBeNull = 1;
int? intCanBeNull = null;
Additionally, in C# many value types have static members so you can do this for example:
string strValue = "123";
intCannotBeNull = int.Parse(strValue);
However you can't do either of these:
intCanBeNull = int?.Parse(strValue);
intCanBeNull = (int?).Parse(strValue);
C# gets confused. Is there a valid syntax that means strValue could be null or a valid integer value and have the assignment work?
I know there are easy workarounds, for example:
intCanBeNull = (strValue == null) ? null : (int?)int.Parse(strValue);
and other variants of the same thing but that's just messy...
int? is syntactic sugar for Nullable<int>. You are asking about Nullable<int>.Parse. There is no such method. That is where your confusion lies.
Parse will not handle null values, It will throw exception. You have to use either TryParse or Convert class to parse
Convert.ToInt32(int or int?)
This applies for long, float, decimal etc..
int? is in fact Nullable<int>. That Nullable<T> struct doesn't have the methods of the T class. Hence, you have to do it yourself.
In the case of int?, you could try something like this:
string s = "1";
int? result;
if (string.IsNullOrEmpty(s))
{
result = null;
}
else
{
int o; // just a temp variable for the `TryParse` call
if (int.TryParse(s, out o))
{
result = o;
}
else
{
result = null;
}
}
// use result

C# IsNullOrZero

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)

Convert null field to zero before converting to int?

In my program, I'm looping through a datatable to get data from each field. One line of my code looks like this:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"]);
Basically, I'm just taking the value that's in the cell and converting it to an int32. I run into a problem, though, when the data in the field is a null. I get an Invalid Cast error message about not being able to convert a "DBNull" to another type.
So, I know that I can just check the value of the field before I try to convert it by doing something like this:
if (resultsDT.Rows[currentRow]["LYSMKWh"] == null)
{
resultsDT.Rows[currentRow]["LYSMKWh"] = 0;
}
But, is there a better way to do this? Is there something I can do "inline" while I'm trying to convert the value without having to resort to using the if ?
EDIT: I did try using this suggested method:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"] ?? "0");
Unfortunately, I still received the Invalid Cast error message with regards to the DBNull type. It was suggested that I could have problems using the ?? operator if the types on either side were different.
Also, since I have complete control over the data that I'm building my datatable with, I changed it so that no null values would be written to any field. So, that pretty much negates the need to convert a null to an int32, in this case. Thanks for all the advice, everyone!
You could do this:
var LYSMKWh =
resultsDT.Rows[currentRow]["LYSMKWh"].Equals(DBNull.Value)
? 0
: Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"]);
use the ?? operator:
resultsDT.Rows[currentRow][...] ?? "0"
(expecting the field to be a string - if not change the "0")
You may consider using C#'s ?? operator, which checks a value for null and if it's null, assigns a default value to it.
You can use the ?? operator:
object x = null;
int i = (int)(x ?? 0)
You can use a custom convert method:
public static int ConvertToInt32(object value, int defaultValue) {
if (value == null)
return defaultValue;
return Convert.ToInt32(value);
}
You may need overloads that take other types, like string. You may have problems with the ?? operator if the types on either side are different.
You can replace it with a ternary operator:
var rowData = resultsDT.Rows[currentRow]["LYSMKWh"];
int LYSMKWh = rowData != null ? Convert.ToInt32(rowData) : 0;
Alternatively, the ?? operator could work:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"] ?? 0);
But I think that's less readable.
You can use extension Method.
int LYSMKWh = resultsDT.Rows[currentRow]["LYSMKWh"].IfNullThenZero();
Create the below class
public static class Converter
{
public static Int32 IfNullThenZero(this object value)
{
if (value == DBNull.Value)
{
return 0;
}
else
{
return Convert.ToInt32(value);
}
}
}
Check if it's DBNull.Value instead of null:
if (resultsDT.Rows[currentRow]["LYSMKWh"] == DBNull.Value)
{
resultsDT.Rows[currentRow]["LYSMKWh"] = 0;
}
The ternary expression would work like this:
var LYSMKwhField = resultsDT.Rows[currentRow]["LYSMKWh"];
int LYSMKWh = LYSMKwhField != DBNull.Value ? Convert.ToInt32(rowData) : 0;

How can I round a C# double nullable type?

I want to round a double? value so that if its value is 2.3 the result should be 2 but if the input is null then the result should be null.
There is no direct way to round a nullable double. You need to check if the variable has a value: if yes, round it; otherwise, return null.
You need to cast a bit if you do this using the conditional ?: operator:
double? result = myNullableDouble.HasValue
? (double?)Math.Round(myNullableDouble.Value)
: null;
Alternatively:
double? result = null;
if (myNullableDouble.HasValue)
{
result = Math.Round(myNullableDouble.Value);
}
As others have pointed out, it is easy enough to do this as a one-off. To do it in general:
static Func<T?, T?> LiftToNullable<T>(Func<T, T> func) where T : struct
{
return n=> n == null ? (T?) null : (T?) func(n.Value);
}
And now you can say:
var NullableRound = LiftToNullable<double>(Math.Round);
double? d = NullableRound(null);
And hey, now you can do this with any method that takes and returns a value type.
return d.HasValue ? Math.Round(d.Value) : (double?)null;

Categories

Resources