C# predicate that returns whether a boxed value type is the default for that type
Is it possible to crea开发者_JS百科te a method that takes a boxed value type and returns whether that value type is equal to the default for that type?
So I want to create a method with the following signature:
bool IsDefault(object boxedValueType);
Note: the following code will not work as T gets set to type object
so default(T)
will always be null
.
bool IsDefault<T>(T input)
{
return Equals(input, default(T));
}
With reflection, but it's a slow method
class Program
{
static void Main(string[] args)
{
Console.WriteLine("1 = " + IsDefault(1));
Console.WriteLine("0 = " + IsDefault(default(int)));
Console.WriteLine("1.0 = " + IsDefault(1.0));
Console.WriteLine("0.0 = " + IsDefault(default(double)));
Console.WriteLine("Today = " + IsDefault(DateTime.Today));
Console.WriteLine("1.1.1 = " + IsDefault(default(DateTime)));
//Console.WriteLine(IsDefault(""));
//Console.WriteLine(IsDefault(default(string)));
Console.ReadKey();
}
static bool IsDefault(object boxedValueType)
{
if (boxedValueType == null) throw new ArgumentNullException("boxedValueType");
var t = boxedValueType.GetType();
if (!t.IsValueType) throw new ArgumentOutOfRangeException("boxedValueType");
object def = Activator.CreateInstance(t);
return boxedValueType.Equals(def);
}
}
You can use reflection to get the default value of the type. See this question about getting default values through reflection. Replace your call to default(T) with a call to that function:
return input.Equals(GetDefault(input.GetType());
Using reflection, you can invoke a generic method using the value's type:
public static bool IsDefault(object value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
return (bool)typeof(Program).GetMethod("IsDefaultGeneric")
.MakeGenericMethod(value.GetType())
.Invoke(null, new object[] { value });
}
public static bool IsDefaultInternal<T>(T value)
where T : struct, IEquatable<T>
{
return value.Equals(default(T));
}
You may be better suited by using nullable types instead of boxed default values. It is easy to test for null
, and nullable types are usually a cleaner design decision than special values.
Code + Unit test which will tell you whether a boxed or unboxed object is its default value. Also included generic version.
[Test]
public void BoxedIntIsDefault()
{
Assert.That(IsDefault((object)0), Is.True);
Assert.That(IsDefault((object)1), Is.False);
Assert.That(IsDefault<object>(0), Is.True);
Assert.That(IsDefault<object>(1), Is.False);
}
bool IsDefault(object obj)
{
return Equals(obj, GetDefault(obj.GetType()));
}
bool IsDefault<T>(T input)
{
return Equals(input, GetDefault(input.GetType()));
}
public static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
if you want to just use the default constructor for the default value it can be
bool IsDefault<T>(T input)
{
return EqualityComparer<T>.Default.Equals(value, Activator.CreateInstance<T>());
}
精彩评论