Sau khi giải quyết vấn đề này trong các hệ thống của riêng tôi, đây là một phương pháp để xác định một cách chính xác giá trị mặc định của một loại tùy vào thời gian chạy, mà đã được thử nghiệm chống lại hàng ngàn loại:
/// <summary>
/// [ <c>public static object GetDefault(this Type type)</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <param name="type">The Type for which to get the default value</param>
/// <returns>The default value for <paramref name="type"/></returns>
/// <remarks>
/// If a null Type, a reference Type, or a System.Void Type is supplied, this method always returns null. If a value type
/// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an
/// exception.
/// </remarks>
/// <example>
/// To use this method in its native, non-extension form, make a call like:
/// <code>
/// object Default = DefaultValue.GetDefault(someType);
/// </code>
/// To use this method in its Type-extension form, make a call like:
/// <code>
/// object Default = someType.GetDefault();
/// </code>
/// </example>
/// <seealso cref="GetDefault<T>"/>
public static object GetDefault(this Type type)
{
// If no Type was supplied, if the Type was a reference type, or if the Type was a System.Void, return null
if (type == null || !type.IsValueType || type == typeof(void))
return null;
// If the supplied Type has generic parameters, its default value cannot be determined
if (type.ContainsGenericParameters)
throw new ArgumentException(
"{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type +
"> contains generic parameters, so the default value cannot be retrieved");
// If the Type is a primitive type, or if it is another publicly-visible value type (i.e. struct/enum), return a
// default instance of the value type
if (type.IsPrimitive || !type.IsNotPublic)
{
try
{
return Activator.CreateInstance(type);
}
catch (Exception e)
{
throw new ArgumentException(
"{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe Activator.CreateInstance method could not " +
"create a default instance of the supplied value type <" + type +
"> (Inner Exception message: \"" + e.Message + "\")", e);
}
}
// Fail with exception
throw new ArgumentException("{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type +
"> is not a publicly-visible type, so the default value cannot be retrieved");
}
Trong các ví dụ này, phương pháp GetDefault được triển khai trong lớp tĩnh DefaultValue. Gọi phương pháp này với một tuyên bố như:
object Default = DefaultValue.GetDefault(someType);
Để sử dụng phương pháp GetDefault như một phương pháp mở rộng cho Type, gọi nó là như thế này:
object Default = someType.GetDefault();
thứ hai này, cách tiếp cận Type-phần mở rộng là một khách hàng đơn giản cú pháp-mã, vì nó loại bỏ sự cần thiết phải tham chiếu vòng loại lớp có chứa DefaultValue trên cuộc gọi.
Biểu mẫu thời gian chạy trên của GetDefault hoạt động với ngữ nghĩa giống hệt như từ khóa C# 'mặc định' nguyên thủy và tạo ra kết quả tương tự.
Để sử dụng một hình thức chung của GetDefault, bạn có thể truy cập vào các chức năng sau:
/// <summary>
/// [ <c>public static T GetDefault< T >()</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <typeparam name="T">The Type for which to get the default value</typeparam>
/// <returns>The default value for Type T</returns>
/// <remarks>
/// If a reference Type or a System.Void Type is supplied, this method always returns null. If a value type
/// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an
/// exception.
/// </remarks>
/// <seealso cref="GetDefault(Type)"/>
public static T GetDefault<T>()
{
return (T) GetDefault(typeof(T));
}
Một cuộc gọi đến các hình thức chung chung có thể là một cái gì đó như:
int? inDefaultVal = DefaultValue.GetDefault<int?>();
Tất nhiên, generic trên hình thức GetDefault là không cần thiết cho C#, vì nó hoạt động giống như mặc định (T). Nó chỉ hữu ích cho một ngôn ngữ .NET không hỗ trợ từ khóa 'mặc định' nhưng nó hỗ trợ các kiểu generic. Trong hầu hết các trường hợp, hình thức chung là không cần thiết.
Phương pháp hệ quả hữu ích là phương pháp xác định xem đối tượng có chứa giá trị mặc định cho Loại của nó hay không. Tôi cũng dựa vào phương pháp IsObjectSetToDefault sau cho mục đích đó:
/// <summary>
/// [ <c>public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue)</c> ]
/// <para></para>
/// Reports whether a value of type T (or a null reference of type T) contains the default value for that Type
/// </summary>
/// <remarks>
/// Reports whether the object is empty or unitialized for a reference type or nullable value type (i.e. is null) or
/// whether the object contains a default value for a non-nullable value type (i.e. int = 0, bool = false, etc.)
/// <para></para>
/// NOTE: For non-nullable value types, this method introduces a boxing/unboxing performance penalty.
/// </remarks>
/// <param name="ObjectType">Type of the object to test</param>
/// <param name="ObjectValue">The object value to test, or null for a reference Type or nullable value Type</param>
/// <returns>
/// true = The object contains the default value for its Type.
/// <para></para>
/// false = The object has been changed from its default value.
/// </returns>
public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue)
{
// If no ObjectType was supplied, attempt to determine from ObjectValue
if (ObjectType == null)
{
// If no ObjectValue was supplied, abort
if (ObjectValue == null)
{
MethodBase currmethod = MethodInfo.GetCurrentMethod();
string ExceptionMsgPrefix = currmethod.DeclaringType + " {" + currmethod + "} Error:\n\n";
throw new ArgumentNullException(ExceptionMsgPrefix + "Cannot determine the ObjectType from a null Value");
}
// Determine ObjectType from ObjectValue
ObjectType = ObjectValue.GetType();
}
// Get the default value of type ObjectType
object Default = ObjectType.GetDefault();
// If a non-null ObjectValue was supplied, compare Value with its default value and return the result
if (ObjectValue != null)
return ObjectValue.Equals(Default);
// Since a null ObjectValue was supplied, report whether its default value is null
return Default == null;
}
Các IsObjectSetToDefault
phương pháp trên hoặc có thể được gọi là ở dạng tự nhiên của nó hoặc truy cập như một phần mở rộng Type-class.
Bạn có thể giải thích lý do tại sao nó không hoạt động? Bạn gặp lỗi? Liệu nó chỉ không trả lại những gì bạn mong đợi? – Gabe
@Josh, Cảm ơn! bạn thích nó – viky
@gabe, Nó hoạt động với tên loại nhưng không phải với loại Ví dụ của tên kiểu đó, tôi có nghĩa là mặc định (Thập phân) hoạt động nhưng mặc định (typeof (Thập phân)) không – viky