nullable types to object - c#

Using dotnet 2.0. Can the following code be improved in style ?
private object GetObj_Version1(int? num)
{
return num ?? (object)DBNull.Value;
}
The cast looks a bit messy to me.
Version2 below avoids the cast, but its long winded :
private object GetObj_Version2(int? num)
{
object numObj;
if (num.HasValue)
numObj = num.Value;
else
numObj = DBNull.Value;
return numObj;
}
Can you think of an alternative which is both short and avoids the cast ? TIA.

The cast, in this case, does nothing at runtime - it is there purely for the compiler. If you really hate it, perhaps:
static readonly object NullObject = DBNull.Value;
private object GetObj_Version1(int? num)
{
return num ?? NullObject;
}
But I'd leave it myself. As an aside - since you are going to box it anyway, you could dispense with the overload, and just work with object - then you don't even need the static field:
private object GetObj_Version1(object value)
{
return value ?? DBNull.Value;
}

If you want to insert values to the database, then you can directly pass the nullable type as a procedure's parameter.
param.Add("#Param1", nullableParam);

Related

A property or indexer may not be passed as an out or ref parameter

I'm getting the above error and unable to resolve it.
I googled a bit but can't get rid of it.
Scenario:
I have class BudgetAllocate whose property is budget which is of double type.
In my dataAccessLayer,
In one of my classes I am trying to do this:
double.TryParse(objReader[i].ToString(), out bd.Budget);
Which is throwing this error:
Property or indexer may not be passed as an out or ref parameter at
compile time.
I even tried this:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
Everything else is working fine and references between layers are present.
Others have given you the solution, but as to why this is necessary: a property is just syntactic sugar for a method.
For example, when you declare a property called Name with a getter and setter, under the hood the compiler actually generates methods called get_Name() and set_Name(value). Then, when you read from and write to this property, the compiler translates these operations into calls to those generated methods.
When you consider this, it becomes obvious why you can't pass a property as an output parameter - you would actually be passing a reference to a method, rather than a reference to an object a variable, which is what an output parameter expects.
A similar case exists for indexers.
This is a case of a leaky abstraction. A property is actually a method, the get and set accessors for an indexer get compiled to get_Index() and set_Index methods. The compiler does a terrific job hiding that fact, it automatically translates an assignment to a property to the corresponding set_Xxx() method for example.
But this goes belly up when you pass a method parameter by reference. That requires the JIT compiler to pass a pointer to the memory location of the passed argument. Problem is, there isn't one, assigning the value of a property requires calling the setter method. The called method cannot tell the difference between a passed variable vs a passed property and can thus not know whether a method call is required.
Notable is that this actually works in VB.NET. For example:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
The VB.NET compiler solves this by automatically generating this code for the Run method, expressed in C#:
int temp = Prop;
Test(ref temp);
Prop = temp;
Which is the workaround you can use as well. Not quite sure why the C# team didn't use the same approach. Possibly because they didn't want to hide the potentially expensive getter and setter calls. Or the completely undiagnosable behavior you'll get when the setter has side-effects that change the property value, they'll disappear after the assignment. Classic difference between C# and VB.NET, C# is "no surprises", VB.NET is "make it work if you can".
you cannot use
double.TryParse(objReader[i].ToString(), out bd.Budget);
replace bd.Budget with some variable.
double k;
double.TryParse(objReader[i].ToString(), out k);
Possibly of interest - you could write your own:
//double.TryParse(, out bd.Budget);
bool result = TryParse(s, value => bd.Budget = value);
}
public bool TryParse(string s, Action<double> setValue)
{
double value;
var result = double.TryParse(s, out value);
if (result) setValue(value);
return result;
}
Place the out parameter into a local variable and then set the variable into bd.Budget:
double tempVar = 0.0;
if (double.TryParse(objReader[i].ToString(), out tempVar))
{
bd.Budget = tempVar;
}
Update: Straight from MSDN:
Properties are not variables and
therefore cannot be passed as out
parameters.
This is a very old post, but I'm ammending the accepted, because there is an even more convienient way of doing this which I didn't know.
It's called inline declaration and might have always been available (as in using statements) or it might have been added with C#6.0 or C#7.0 for such cases, not sure, but works like a charm anyway:
Inetad of this
double temp;
double.TryParse(objReader[i].ToString(), out temp);
bd.Budget = temp;
use this:
double.TryParse(objReader[i].ToString(), out double temp);
bd.Budget = temp;
So Budget is a property, correct?
Rather first set it to a local variable, and then set the property value to that.
double t = 0;
double.TryParse(objReader[i].ToString(), out t);
bd.Budget = t;
Usually when I'm trying to do this it's because I want to set my property or leave it at the default value. With the help of this answer and dynamic types we can easily create a string extension method to keep it one lined and simple.
public static dynamic ParseAny(this string text, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null && converter.IsValid(text))
return converter.ConvertFromString(text);
else
return Activator.CreateInstance(type);
}
Use like so;
bd.Budget = objReader[i].ToString().ParseAny(typeof(double));
// Examples
int intTest = "1234".ParseAny(typeof(int)); // Result: 1234
double doubleTest = "12.34".ParseAny(typeof(double)); // Result: 12.34
decimal pass = "12.34".ParseAny(typeof(decimal)); // Result: 12.34
decimal fail = "abc".ParseAny(typeof(decimal)); // Result: 0
string nullStr = null;
decimal failedNull = nullStr.ParseAny(typeof(decimal)); // Result: 0
Optional
On a side note, if that's an SQLDataReader you may also make use of GetSafeString extension(s) to avoid null exceptions from the reader.
public static string GetSafeString(this SqlDataReader reader, int colIndex)
{
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
public static string GetSafeString(this SqlDataReader reader, string colName)
{
int colIndex = reader.GetOrdinal(colName);
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
Use like so;
bd.Budget = objReader.GetSafeString(i).ParseAny(typeof(double));
bd.Budget = objReader.GetSafeString("ColumnName").ParseAny(typeof(double));
I had the same problem (5 minutes ago) and I solved it using old style properties with getter and setter, whose use variables.
My code:
public List<int> bigField = new List<int>();
public List<int> BigField { get { return bigField; } set { bigField = value; } }
So, I just used bigField variable. I'm not the programmer, if I misunderstood the question, I'm really sorry.

Concise usage of DBNull? (Ternary?)

It seems that there's some type confusion in the ternary operator. I know that this has been addressed in other SO threads, but it's always been with nullables. Also, for my case I'm really just looking for a better way.
I'd like to be able to use
proc.Parameters[PARAM_ID].Value =
string.IsNullOrEmpty(dest.Id) ? DBNull.Value : dest.Id;
but instead I'm stuck with this:
if (string.IsNullOrEmpty(dest.Id))
{
proc.Parameters[PARAM_ID].Value = DBNull.Value;
}
else
{
proc.Parameters[PARAM_ID].Value = dest.Id;
}
The ternary operator fails because there's no conversion possible between DBNull and string, and as silly as that seems considering Value is object, the compiler kicks it back to me and I'm forced to care. The answer to the nullable version of this question is to just cast null to string and be done with it; DBNull can't be cast to string, though, so no luck there.
Is there a more concise way to do this (without using nullables, by the way?)
Thanks!
You could change your first statement to:
proc.Parameters[PARAM_ID].Value =
string.IsNullOrEmpty(dest.Id) ? (object)DBNull.Value : dest.Id;
The Value property is of type object, so you should cast to object, not string:
proc.Parameters[PARAM_ID].Value = string.IsNullOrEmpty(dest.Id)
? (object)DBNull.Value
: (object)dest.Id;
Or you could add an extension method such as:
public static class DBNullExtensions
{
public static object AsDBNullIfEmpty(this string value)
{
if (String.IsNullOrEmpty(value))
{
return DBNull.Value;
}
return value;
}
}
And then you could just say
proc.Parameters[PARAM_ID].Value = dest.Id.AsDBNullIfEmpty();
(Adapted from Phil Haack)
Readable and concise, no?
What about using the ?? null-coalescing operator More details about ?? operator
proc.Parameters[PARAM_ID].Value = dest.Id ?? (object)DBNull.Value;

How Can I Compare Any Numeric Type To Zero In C#

I would like to create a function that checks if a numeric value passed as an argument has a value greater than zero. Something like this:
public bool IsGreaterThanZero(object value)
{
if(value is int)
{
return ((int)value > 0);
}
else if(value is float)
{
// Similar code for float
}
return false;
}
Can I try to cast the object passed as the function's argument to one numeric data type so I can then compare it to zero rather than checking for each type in my if statement? If the cast fails I would return false. Is there a better(read shorter, more readable) way to do this?
Edit:
Some have asked about if I know the type will be a numeric, why the object etc. I hope this makes things clearer.
This function would be part of a Silverlight converter that implements the IValueConverter interface which has a convert signature of
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
A first, I only wanted the converter to work with ints but my imagination started to run wild and think what if I have floating point numbers and other numeric types. I wanted to make the converter as flexible as possible. Initially I thought all this extra information would get in the way of what I wanted to do so I didn't include it in my question.
Does the caller know the type? If so, how about:
public static bool GreaterThanZero<T>(T value) where T : struct, IComparable<T>
{
return value.CompareTo(default(T)) > 0;
}
No conversions needed, and should work for any of the built-in numeric types - and any sensible value types you come up with yourself. (For example, this would be fine with Noda Time's Duration struct.)
Note that the caller doesn't have to know the type directly - it may only know it as another type parameter with the same constraints. Admittedly this may not be appropriate for your situation, but I thought I'd mention it anyway. If nothing knows the type at compile-time (and you don't fancy getting dynamic typing to do the job for you in C# 4!) then calling Convert.ToDouble is probably your best bet - just be aware that it may have problems for System.Numerics.BigInteger from .NET 4.0.
My preference would be:
public bool IsGreaterThanZero(object value)
{
if(value is IConvertible)
{
return Convert.ToDouble(value) > 0.0;
}
return false;
}
This will handle all IConvertible types safely (which includes all floating point and integer types in the framework, but also any custom types).
Eh? What numeric types do you care about?
public bool IsGreaterThanZero(double value)
{
return value > 0;
}
These all work ...
IsGreaterThanZero((int)2);
IsGreaterThanZero((long)2);
IsGreaterThanZero((double)2);
IsGreaterThanZero((float)2);
IsGreaterThanZero((byte)2);
IsGreaterThanZero((ulong)2);
You can avoid boxing and unboxing using generics:
Here's the definition of a function
class GenericComparation {
public static bool IsGreaterThanZero<T>(T value) where T : IComparable<T> {
// Console.WriteLine(value.GetType().Name)
return value.CompareTo(default(T)) > 0;
}
}
Usage:
Console.WriteLine(GenericComparation.IsGreaterThanZero(1));
Console.WriteLine(GenericComparation.IsGreaterThanZero(-1.1));
Console.WriteLine(GenericComparation.IsGreaterThanZero(Decimal.Zero));
Try:
double tempValue;
if(double.TryParse(value.ToString(), out tempValue)
{
return (tempValue > 0)
}
else
{
return false;
}
Why not just Convert.ToDouble or Convert.ToDecimal and then do the comparison? Seems like that would handle most types that someone might pass in.
This simplest and fastest way to compare any numeric type To zero is as follows:
public bool IsGreaterThanZero(object value)
{
if (value != null && value.GetType().IsValueType)
return System.Convert.ToDouble(value) > 0;
return false;
}

Is this the best approach using generics to check for nulls?

public static T IsNull<T>(object value, T defaultValue)
{
return ((Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)) ?
defaultValue : (T)value);
}
public static T IsNull<T>(object value) where T :new()
{
T defaultvalue = new T();
return IsNull(value, defaultvalue);
}
Have tested, and can use against data objects, classes and variables.
Just want to know if there is better way to go about this.
It looks like you're trying to duplicate the null coalesce operator:
var foo = myPossiblyNullValue ?? defaultValue;
First off, the method name is wrong. You imply that the result of the function is a boolean that is true exactly if the given value is null. In fact, that’s not the case. GetValueOrDefault might be a better name.
Secondly, you’re merely replicating the behaviour of the null coalesce operator, as mentioned by others.
Thirdly, your conditional is odd:
Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)
Why Object.Equals instead of ==? Better yet, use Object.ReferenceEquals since that makes it clear that you’re interested in reference equality. Also, you’re using the bitwise-or operator (|) which is semantically wrong in this context, although it happens to yield the right value. You want the boolean-or operator ||. (Also, inconsistency: why do you sometimes write object and other times Object?)
Finally, using type object instead of a generic type isn’t necessarily a good solution. It would be better to create overloads for generic reference and value types: this avoids boxing in the value types. It also means that you don’t have to specify the type explicitly in your second overload since it can be deduced from the method argument.
public static bool IsNull<T>(object value)
{
return object == default(T);
}
[Edited]
The following (non-generic) should work.
public static bool IsNull(object value)
{
return value == null;
}
Any value type will get boxed (i.e. non-null). Ref types will just be passed by pointer.

C# int to enum conversion [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Cast int to enum in C#
If I have the following code:
enum foo : int
{
option1 = 1,
option2,
...
}
private foo convertIntToFoo(int value)
{
// Convert int to respective Foo value or throw exception
}
What would the conversion code look like?
It's fine just to cast your int to Foo:
int i = 1;
Foo f = (Foo)i;
If you try to cast a value that's not defined it will still work. The only harm that may come from this is in how you use the value later on.
If you really want to make sure your value is defined in the enum, you can use Enum.IsDefined:
int i = 1;
if (Enum.IsDefined(typeof(Foo), i))
{
Foo f = (Foo)i;
}
else
{
// Throw exception, etc.
}
However, using IsDefined costs more than just casting. Which you use depends on your implemenation. You might consider restricting user input, or handling a default case when you use the enum.
Also note that you don't have to specify that your enum inherits from int; this is the default behavior.
I'm pretty sure you can do explicit casting here.
foo f = (foo)value;
So long as you say the enum inherits(?) from int, which you have.
enum foo : int
EDIT Yes it turns out that by default, an enums underlying type is int. You can however use any integral type except char.
You can also cast from a value that's not in the enum, producing an invalid enum. I suspect this works by just changing the type of the reference and not actually changing the value in memory.
enum (C# Reference)
Enumeration Types (C# Programming Guide)
Casting should be enough. If you're using C# 3.0 you can make a handy extension method to parse enum values:
public static TEnum ToEnum<TInput, TEnum>(this TInput value)
{
Type type = typeof(TEnum);
if (value == default(TInput))
{
throw new ArgumentException("Value is null or empty.", "value");
}
if (!type.IsEnum)
{
throw new ArgumentException("Enum expected.", "TEnum");
}
return (TEnum)Enum.Parse(type, value.ToString(), true);
}
if (Enum.IsDefined(typeof(foo), value))
{
return (Foo)Enum.Parse(typeof(foo), value);
}
Hope this helps
Edit
This answer got down voted as value in my example is a string, where as the question asked for an int. My applogies; the following should be a bit clearer :-)
Type fooType = typeof(foo);
if (Enum.IsDefined(fooType , value.ToString()))
{
return (Foo)Enum.Parse(fooType , value.ToString());
}
You don't need the inheritance. You can do:
(Foo)1
it will work ;)

Categories

Resources