patterncsharpMinor
Conversion helper with support for enumerations and Nullable<T>
Viewed 0 times
conversionenumerationshelperwithnullableforandsupport
Problem
I recently wrote this code as a more versatile stand-in for
```
///
/// Returns an object of type whose value is equivalent to that of the specified
/// object.
///
///
/// The output type.
///
///
/// An object that implements or is where the underlying
/// type implements .
///
///
/// An object whose type is and whose value is equivalent to .
///
///
/// The specified value is not defined by the enumeration (when is an enum, or Nullable{T}
/// where the underlying type is an enum).
///
///
/// This method works similarly to with the addition of support
/// for enumerations and where the underlying type is .
///
internal static T ChangeType(object value) {
Type type = typeof(T);
Type underlyingNullableType = Nullable.GetUnderlyingType(type);
if ((underlyingNullableType ?? type).IsEnum) {
// The specified type is an enum or Nullable{T} where T is an enum.
T convertedEnum = (T)Enum.ToObject(underlyingNullableType ?? type, value);
if (!Enum.IsDefined(underlyingNullableType ?? type, convertedEnum)) {
throw new ArgumentException("The specified value is not defined by the enumeration.", "value");
}
return convertedEnum;
} else if (type.IsValueType && underlyingNullableType == null) {
// The specified type is a non-nullable value type.
if (value == null || DBNull.Value.Equals(value)) {
throw new InvalidCastException("Cannot convert a null value to a non-nullable type.");
}
return (T)Convert.ChangeType(value, type);
}
// The specified type is a reference type or Nullable{T} where
Convert.ChangeType. I have a nagging feeling that there's something I might be overlooking, or that there might be a more efficient algorithm for this.```
///
/// Returns an object of type whose value is equivalent to that of the specified
/// object.
///
///
/// The output type.
///
///
/// An object that implements or is where the underlying
/// type implements .
///
///
/// An object whose type is and whose value is equivalent to .
///
///
/// The specified value is not defined by the enumeration (when is an enum, or Nullable{T}
/// where the underlying type is an enum).
///
///
/// This method works similarly to with the addition of support
/// for enumerations and where the underlying type is .
///
internal static T ChangeType(object value) {
Type type = typeof(T);
Type underlyingNullableType = Nullable.GetUnderlyingType(type);
if ((underlyingNullableType ?? type).IsEnum) {
// The specified type is an enum or Nullable{T} where T is an enum.
T convertedEnum = (T)Enum.ToObject(underlyingNullableType ?? type, value);
if (!Enum.IsDefined(underlyingNullableType ?? type, convertedEnum)) {
throw new ArgumentException("The specified value is not defined by the enumeration.", "value");
}
return convertedEnum;
} else if (type.IsValueType && underlyingNullableType == null) {
// The specified type is a non-nullable value type.
if (value == null || DBNull.Value.Equals(value)) {
throw new InvalidCastException("Cannot convert a null value to a non-nullable type.");
}
return (T)Convert.ChangeType(value, type);
}
// The specified type is a reference type or Nullable{T} where
Solution
///
/// Returns an object of type whose value is equivalent to that of the specified
/// object.
///
...
///
/// An object whose type is and whose value is equivalent to .
/// I don't see any reason to repeat what was said in `
in . I wouldn't write here at all. (Unless you're writing a library with very high demands on documentation, like the .Net framework itself.)
underlyingNullableType ?? type
You're repeating this expression several times. You should probably extract it into a variable.
You should be consistent: either use if-else if-else and ignore the returns, or acknowledge the returns and use if-if`-nothing.Code Snippets
/// <summary>
/// Returns an object of type <typeparamref name="T"/> whose value is equivalent to that of the specified
/// object.
/// </summary>
...
/// <returns>
/// An object whose type is <typeparamref name="T"/> and whose value is equivalent to <paramref name="value"/>.
/// </returns>underlyingNullableType ?? typeContext
StackExchange Code Review Q#74322, answer score: 4
Revisions (0)
No revisions yet.