How to check if boxed value is empty in .NET - c#

For example,
I have input parameter of type object. And I know that this parameter can store one of value type int, float, double(boxed value) etc. But I don't know which value type will come to this method. And I want check if boxed value type empty or not.
Like this piece of code:
bool IsEmpty(object boxedProperty)
{
return boxedProperty == default(typeof(boxedProperty))
}
I understand, I can do this:
bool IsEmpty(object boxedProperty)
{
return boxedProperty is int && boxedProperty == default(int)
|| boxedProperty is float ....
}
But it looks like dirty solution. How do this better?

I guess something like this can give you a result for reference + boxed value types.
public bool IsDefaultValue(object o)
{
if (o == null)
return true;
var type = o.GetType();
return type.IsValueType && o.Equals(Activator.CreateInstance(type));
}
object i = default(int);
object j = default(float);
object k = default(double);
object s = default(string);
object i2 = (int)2;
object s2 = (string)"asas";
var bi = IsDefaultValue(i); // true
var bj = IsDefaultValue(j); // true
var bk = IsDefaultValue(k); // true
var bs = IsDefaultValue(s); // true
var bi2 = IsDefaultValue(i2); // false
var bs2 = IsDefaultValue(s2); // false
If you are shure you have a value type, then use this method:
public bool IsDefaultBoxedValueType(object o)
{
return o.Equals(Activator.CreateInstance(o.GetType()));
}

As others have pointed out the only real way to do it is to create an instance of the type and then compare it. (see also how to get the default value of a type if the type is only known as System.Type? and Default value of a type at Runtime)
You can cache the results so you only have to create a default instance 1x type. This can increase efficiency if you have to call the check many times. I used a static method and dictionary (its not thread safe) but you could change it to instance level if you wanted.
static IDictionary<Type, object> DefaultValues = new Dictionary<Type, object>();
static bool IsBoxedDefault(object boxedProperty)
{
if (boxedProperty == null)
return true;
Type objectType = boxedProperty.GetType();
if (!objectType.IsValueType)
{
// throw exception or something else?? Up to how you want this to behave
return false;
}
object defaultValue = null;
if (!DefaultValues.TryGetValue(objectType, out defaultValue))
{
defaultValue = Activator.CreateInstance(objectType);
DefaultValues[objectType] = defaultValue;
}
return defaultValue.Equals(boxedProperty);
}
Test code
static void Test()
{
Console.WriteLine(IsBoxedDefault(0)); // true
Console.WriteLine(IsBoxedDefault("")); // false (reference type)
Console.WriteLine(IsBoxedDefault(1));// false
Console.WriteLine(IsBoxedDefault(DateTime.Now)); // false
Console.WriteLine(IsBoxedDefault(new DateTime())); // true
}

Looks to my like a generic function is a fine way to go. Something similar to:
static void Main(string[] args)
{
object obj1 = null;
object obj2 = "Assigned value";
Console.WriteLine(string.Format("IsEmpty(obj1) --> {0}", IsEmpty(obj1)));
Console.WriteLine(string.Format("IsEmpty(obj2) --> {0}", IsEmpty(obj2)));
Console.ReadLine();
}
private static bool IsEmpty<T>(T boxedProperty)
{
T defaultProperty = default(T);
return ReferenceEquals(boxedProperty, defaultProperty);
}
Outputs:
IsEmpty(obj1) --> True
IsEmpty(obj1) --> False

Related

.Net dynamic list conversion

I have to do a comparison of 2 lists. The problem is that I don't know of what type the field inside the list are, they can be int, string, decimal, enums or even other objects.
I will know the type only on runtime. I was thinking of creating a list of object and cast them to object the problem is that let's say I have a List<int> and I'm trying to cast it to object it fails.
Another problem is that I know there is a list only on runtime. so on runtime I need to transform the variable of type object to a list.
How can I cast that object to List and how can I cast it to let's say list of objects?
Update:
I have and object and by reflection I'm getting the the property of it with
var oldProperty = property.GetValue(old);
var newProperty = property.GetValue(new);
Once I have the properties values and I can see it's a list I will need to compare those 2. Let's say oldProperty is of type List
I've tried to do something like:
var myOldList = (List<object>)oldProperty;
If the cast fails with
Unable to cast object of type 'System.Collections.Generic.List`1[System.Int32]' to type 'System.Collections.Generic.List`1[System.Object]'
Here you have a look of the function i;m trying to create. Please don't mind of null objects(is not in the scope)
public void SetDifference(object first, object second)
{
var properties = first.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
var oldValue = property.GetValue(first);
var newValue = property.GetValue(second);
if (Convert.GetTypeCode(newValue) != TypeCode.Object)
{
if (!oldValue.Equals(newValue))
{
result.AddDifference(new PrimitiveComparison()
{
BeforeValue = oldValue.ToString(),
AfterValue = newValue.ToString(),
PropertyName = property.Name
});
}
}
else
{
if (property.PropertyType.Name.Contains("List"))
{
// here fails with the error from above
var oldList = (List<object>)oldValue;
var newList = (List<object>)newValue;
if (oldList.Count != newList.Count)
{
result.AddDifference(new PrimitiveComparison()
{
BeforeValue = oldList.Count.ToString(),
AfterValue = newList.Count.ToString(),
PropertyName = property.Name + "Count"
});
}
// add the list differences
result.AddDifference(SetListDifference(oldList, newList);
}
else
{
var diffrence = SetDifference(oldValue, newValue);
if (!diffrence.areEqual)
{
result.AddDifference(diffrence);
}
}
}
}
}
You can just cast your two values to IList and compare them, for example like this:
static bool AreEqual(IList first, IList second) {
if (first.Count != second.Count)
return false;
for (int i = 0; i < first.Count; i++) {
if (!object.Equals(first[i], second[i]))
return false;
}
return true;
}
once you do conversion of you list than you can check both the list have same element or not by using except method of linq, to find both are equal or not
double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
if(onlyInFirstSet.Count() ==0)
Console.WriteLine("equal");
for primitive type this works fine but for user defined type you need compare implementation.
Check this blog post for comparing list of two different type : Difference between list of user defined types
If you are aware that is going to be IEnumerable type than you can try
List<object> objlst = (value as IEnumerable<object>).Cast<object>
().ToList()
you can try like this
Type t = typeof(obj);
if (t == typeof(List<int>)) {
var lst= (List<int>)obj;
} else if (t == typeof(List<string>)) {
var lst = (List<string>)obj;
} else if (t == typeof(List<decimal>)) {
var lst = (List<decimal>)obj;
}
else if (t == typeof(List<EnumName>)) {
var lst = (List<EnumName>)obj;
}

Generic extension method for retrieving 'default' value?

I'm playing around a bit with determining the default values of objects, based on the example here:
https://stackoverflow.com/a/3195792/1293496
This particular extension method was created for System.Type. What I was trying to accomplish was to make this even more generic, where I could do something like this:
int i = 3;
bool amIaDefaultValue = i.IsDefaultValue();
I would expect this to return true if i == 0 (the default value for an int), and false for all other instances.
Here is my initial attempt:
public static bool IsDefaultValue<T>(this T value)
{
var t = typeof(T); // always comes back as object..?
if (t.IsValueType && Nullable.GetUnderlyingType(t) == null)
{
return value.Equals(Activator.CreateInstance<T>());
}
else
{
var defaultValue = default(T);
if (value == null)
return defaultValue == null;
else
return value.Equals(defaultValue);
}
}
On the plus side, I'm able to attach .IsDefaultValue() to any object. Unfortunately, the type of T always comes back as System.Object. I can get the correct type if I set it up this way:
var t = typeof(value);
But if the value happens to be null, I'll get an error straight away. Is there a good workaround for implementing an extension method like this? Or should I stick to the tried and tested route from the example?
Edit
As pointed out by comments, it seems I oversimplified this a bit and missed the root of the problem. Here's what was actually calling my IsDefaultValue():
foreach (var imprintProperty in deltas.GetType().GetProperties())
{
var value = imprintProperty.GetValue(deltas);
if (!value.IsDefaultValue())
{
// get corresponding prop in programmable area
var programmableProp = progarea.GetType().GetProperty(imprintProperty.Name);
if (programmableProp != null)
programmableProp.SetValue(progarea, value);
}
}
And now it becomes obvious that .GetValue is always returning as System.Object. Uff.
Is it still possible to treat the object as its underlying type in the extension method? Sorry for the confusion with this.
Take a look at this:
static class Program
{
static void Main()
{
int a = 1;
Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());
a = 0;
Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());
object obj = new object();
Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());
obj = null;
Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());
int? b = 1;
Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());
b = null;
Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());
Console.ReadKey(true);
}
static bool IsDefaultValue<T>(this T value)
{
if (ReferenceEquals(value, null))
{
return true;
}
var t = value.GetType();
if (t.IsValueType)
{
return value.Equals(Activator.CreateInstance(value.GetType()));
}
return false;
}
}
Apparently works (I've to say that I was convinced that the other way should have worked but not)

Comparing numeric Value stored in object >= to another object

In my program, i'm reading SchemData from a table.
I need to determine the column size and decide at runtime if a given value
matches the column size and could be written to that column.
In case of alpha-numeric Types like char, nvarchar,... this is no problem.
But in case of numeric values i cannot compare the value with the column size, because column size will give me the amount of bytes to store inside that column, if my understanding here is correct.
So i want to check, if my numeric values are inside the MaxValue range of that particular data type stored inside a System.Type variable of that column.
I started with determining the MaxValue using reflection and also recognizing nullable types like that:
public static Object GetMaxValue(this Type type)
{
var t = GetNullableType(type);
var f = t.GetField("MaxValue");
if (f == null)
return null;
else
return f.GetValue(null);
}
public static Type GetNullableType(Type type)
{
Type retType = type;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var nullableConverter = new System.ComponentModel.NullableConverter(type);
retType = nullableConverter.UnderlyingType;
}
return retType;
}
Now i get an object, storing the MaxValue information.
How can i compare the MaxValue stored inside an object with another value, stored inside another object (or maybe a string).
The value inside the second object (or string, as mentioned before) are read from a xml file, therefor this is not a specific type like int. It needs to be from type object.
The only thing to solve the comparison thing i thought of was implementing a method and checking for every single numeric type inside a switch and performing a try parse and return true/false.
First example method looks like this:
public static bool TestMaxValue(this Type type, object compare)
{
var t = GetNullableType(type);
var mv = t.GetMaxValue();
bool ret = false;
switch (Type.GetTypeCode(t))
{
case TypeCode.Byte:
{
Byte b;
if (Byte.TryParse(compare.ToString(), out b))
ret =(Convert.ToByte(mv) >= b);
break;
}
case TypeCode.Decimal:
{
Decimal b;
if (Decimal.TryParse(compare.ToString(), out b))
ret = (Convert.ToDecimal(mv) >= b);
break;
}
case TypeCode.Double:
{
Double b;
if (Double.TryParse(compare.ToString(), out b))
ret = (Convert.ToDouble(mv) >= b);
break;
}
case TypeCode.Int16:
{
Int16 b;
if (Int16.TryParse(compare.ToString(), out b))
ret = (Convert.ToInt16(mv) >= b);
break;
}
case TypeCode.Int32:
{
Int32 b;
if (Int32.TryParse(compare.ToString(), out b))
ret = (Convert.ToInt32(mv) >= b);
break;
}
}
return ret;
}
Does anyone have a better idea than implementing such a method?
Thanks in advance.
You can use Convert.ChangeType and IComparable to solve this. All primitive types are inherited from IComparable.
This snippet is working at my end.
Make sure u catch the exception inside or outside as ChangeType throws format exception if the conversion type is incorrect.
public static bool TestMaxValue(this Type type, object compare)
{
var t = GetNullableType(type);
var mv = t.GetMaxValue();
bool ret = false;
try
{
IComparable maxValue = Convert.ChangeType(mv, t) as IComparable;
IComparable currentValue = Convert.ChangeType(compare, t) as IComparable;
if (maxValue != null && currentValue != null)
ret = maxValue.CompareTo(currentValue) > 0;
}
catch (FormatException exception)
{
//handle is here
ret = false;
}
return ret;
}
Although its recommended to not write extension methods as it reduces type safety. Create extension methods for specific types separately like
public static bool TestMaxValue(this int? value, int compareValue)
{
var intValue = value.GetValueOrDefault();
var ret = intValue.CompareTo(compareValue) > 0;
return ret;
}

Nullable.GetUnderlyingType is not Working Properly

I have the following code:
Tuple<string, string, Type, ParameterInfo[]> method = (Tuple<string, string, Type, ParameterInfo[]>)(comboBox1.SelectedItem);
if (comboBox2.SelectedIndex - 1 >= 0)
{
if (method.Item4[comboBox2.SelectedIndex - 1].ParameterType.BaseType == typeof(Enum))
{
foreach (object type in Enum.GetValues(method.Item4[comboBox2.SelectedIndex - 1].ParameterType))
{
Console.WriteLine(type);
}
MessageBox.Show("This looks like an auto-generated type; you shouldn't set it to anything.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
}
else if (Nullable.GetUnderlyingType(method.Item4[comboBox2.SelectedIndex - 1].ParameterType) != null)
{
if (Nullable.GetUnderlyingType(method.Item4[comboBox2.SelectedIndex - 1].ParameterType).BaseType == typeof(Enum))
{
MessageBox.Show("This looks like an auto-generated type; you shouldn't set it to anything.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
}
}
}
On the else if statement, I noticed that it always returns null, even though the object at method.Item4[0] in my case is always a Nullable type when the comboBox2.SelectedIndex is 1, so why is it returning null? Seriously, I put a break-point there, and in Item4, I see the object at index 0 as:
[0] = {System.Nullable`1[CarConditionEnum]& carCondition}
...and at index 1 as:
[1] = {Boolean& carConditionSpecified}
The problem is the parameter is a by reference type i.e. it is declared as ref CarConditionEnum? paramName.
You need to get the element type of the parameter, and then use Nullable.GetUnderlyingType:
Type paramType = method.Item4[comboBox2.SelectedIndex - 1].ParameterType;
if(paramType.HasElementType)
{
paramType = paramType.GetElementType();
}
if(Nullable.GetUnderlyingType(paramType) != null)
{
}
The problem is that the parameter is ref or out which I can see from the ampersand & character. At first I didn't know how to remove that, but it turned out (the other answer) that you use GetElementType() for that.
I reproduce your findings like this:
var t1 = typeof(int?);
string s1 = t1.ToString(); // "System.Nullable`1[System.Int32]"
bool b1 = Nullable.GetUnderlyingType(t1) != null; // true
var t2 = t1.MakeByRefType();
string s2 = t2.ToString(); // "System.Nullable`1[System.Int32]&"
bool b2 = Nullable.GetUnderlyingType(t2) != null; // false
// remove the ByRef wrapping
var t3 = t2.GetElementType();
string s3 = t3.ToString(); // "System.Nullable`1[System.Int32]"
bool b3 = Nullable.GetUnderlyingType(t3) != null; // true
Here, t1 and t3 are the same type, ReferenceEquals(t1, t3).

How do I pass in an Enum as a parameter such that it can be used to perform a cast?

In the stub below how do I pass in (MyEnum) as a parameter such that I can use this procedure with any enum?
public static Enum Proc(this Enum e)
{
Int32 i = (Int32)(MyEnum)e;
...
Here is the solution I have come up with that works:
public static Enum Next(this Enum e, Type eT)
{
Int32 i = (Int32)(Object)e;
return (Enum)Enum.Parse(eT, Enum.GetName(eT, Enum.GetName(eT, ++i) == null? i = 0 : i));
}
This solution isn't ideal because I have to do this to get the next value:
MyEnum e = (MyEnum)e.Next(typeof(MyEnum));
I'd rather just do
MyEnum e = e.Next(typeof(MyEnum));
Or even better:
MyEnum e = e.Next();
Anyone who can provide the simple solution can have the point.
Also the code I've written above runs fine in LinqPad but only compiles in WP7 and then throws an exception when I run it (InvalidProgramException).
Here's a function that will cycle through the values of any enum:
static public Enum Cycle(this Enum e)
{
bool found = false;
Enum first = null;
foreach (Enum i in Enum.GetValues(e.GetType()))
{
if (first == null)
first = i;
if (found)
return i;
found = e.Equals(i);
}
if (found)
return first;
return null;
}
For versions of C# that don't have Enum.GetValues, you'll have to use a method like this which only works for enums whose values start at 0 and increment by 1:
static public Enum Cycle(this Enum e)
{
var i = ((IConvertible)e).ToInt64(null) + 1;
var eT = e.GetType();
var next = Enum.GetName(eT, i);
return (Enum)Enum.Parse(eT, next ?? Enum.GetName(eT, 0), false);
}
Use it like:
var nextEnum = (MyEnum)curEnum.Cycle();
Edit: I updated this to return the next enum in the list, strongly typed, regardless of what the numbering of the enum values may be. I'm able to compile and run this under .NET 4 and haven't tried it on WP7, but I don't think I'm using anything that's missing/disabled in SL/WP7.
public static T Next<T>(this T e) where T : struct
{
var t = typeof(T);
if (!t.IsEnum) throw new ArgumentException("T must be an enumerated type");
if (!Enum.IsDefined(t, e)) throw new ArgumentException();
var intValue = (int)t.GetField(e.ToString()).GetValue(null);
var enumValues = t.GetFields(BindingFlags.Public | BindingFlags.Static).Select(x => x.GetValue(null));
var next = (T?)enumValues.Where(x => (int)x > intValue).Min();
if (next.HasValue)
return next.Value;
else
return (T)enumValues.Min();
}
It can be used as simply as:
var nextE = e.Next();

Categories