I'm creating an extension method that can be used on any type. The idea is that if this method is called, it checks if value is null. If null, it needs to return a default instance of the specified type.
public static dynamic CreateDefaultIfNull<T>(this object item)
{
if(item == null)
{
var type = typeof(T);
if(type.IsArray)
{
return Array.CreateInstance(type.GetElementType(), 0);
}
if(type.GetConstructor(Type.EmptyTypes) == null)
{
var paramCount = type.GetConstructors().First().GetParameters().Count();
var paramNullList = new List<object>();
for(int i = 0; i < paramCount; i++)
{
paramNullList.Add(null);
}
return Activator.CreateInstance(type, paramNullList.ToArray());
}
return Activator.CreateInstance(type);
}
return (T)item;
}
I'm looking for a review of my code, and any pitfalls that I may encounter or may have missed.
The idea is that this method should be used anytime that a null value cannot be used and a default must be returned.
I'm not worried about null values being passed into parameterized constructors, as this is doing. The constructor of those objects should be handling if null values are passed into their constructors.
EDIT: Based on the information provided, I've updated my code. The current version is below:
public static dynamic CreateDefaultIfNull<T>(this T item)
{
if (item != null)
return item;
var type = typeof(T);
if (type.IsArray)
{
return Array.CreateInstance(type.GetElementType(), 0);
}
if (type.GetConstructor(Type.EmptyTypes) == null)
{
var paramCount = type.GetConstructors().Min(construct => construct.GetParameters().Count());
var constructorToUse = type.GetConstructors().Where(construct => construct.GetParameters().Count() == paramCount).First();
var paramNullList = new object[paramCount];
var parameters = constructorToUse.GetParameters();
for (int i = 0; i < paramCount; i++)
{
paramNullList[i] = parameters[i].ParameterType.IsValueType ? Activator.CreateInstance(parameters[i].ParameterType) : null;
}
return Activator.CreateInstance(type, paramNullList);
}
return Activator.CreateInstance(type);
}
int
)? Will assigningnull
to it blow up? \$\endgroup\$object
and returnsdynamic
. You couldn't just useT
? Then you'd get type inference at the call site, which might be nice. \$\endgroup\$