Tôi có một vài phương pháp tôi đã viết trong thư viện tiện ích của tôi mà tôi đã dựa nhiều vào. Đầu tiên là một phương pháp có thể chuyển đổi bất kỳ loại để Nullable < Loại hình thức > tương ứng của nó:
/// <summary>
/// [ <c>public static Type GetNullableType(Type TypeToConvert)</c> ]
/// <para></para>
/// Convert any Type to its Nullable<T> form, if possible
/// </summary>
/// <param name="TypeToConvert">The Type to convert</param>
/// <returns>
/// The Nullable<T> converted from the original type, the original type if it was already nullable, or null
/// if either <paramref name="TypeToConvert"/> could not be converted or if it was null.
/// </returns>
/// <remarks>
/// To qualify to be converted to a nullable form, <paramref name="TypeToConvert"/> must contain a non-nullable value
/// type other than System.Void. Otherwise, this method will return a null.
/// </remarks>
/// <seealso cref="Nullable<T>"/>
public static Type GetNullableType(Type TypeToConvert)
{
// Abort if no type supplied
if (TypeToConvert == null)
return null;
// If the given type is already nullable, just return it
if (IsTypeNullable(TypeToConvert))
return TypeToConvert;
// If the type is a ValueType and is not System.Void, convert it to a Nullable<Type>
if (TypeToConvert.IsValueType && TypeToConvert != typeof(void))
return typeof(Nullable<>).MakeGenericType(TypeToConvert);
// Done - no conversion
return null;
}
Phương pháp thứ hai chỉ đơn giản là báo cáo cho dù một loại nhất định là nullable.Phương pháp này được gọi bởi người đầu tiên và rất hữu ích riêng:
/// <summary>
/// [ <c>public static bool IsTypeNullable(Type TypeToTest)</c> ]
/// <para></para>
/// Reports whether a given Type is nullable (Nullable< Type >)
/// </summary>
/// <param name="TypeToTest">The Type to test</param>
/// <returns>
/// true = The given Type is a Nullable< Type >; false = The type is not nullable, or <paramref name="TypeToTest"/>
/// is null.
/// </returns>
/// <remarks>
/// This method tests <paramref name="TypeToTest"/> and reports whether it is nullable (i.e. whether it is either a
/// reference type or a form of the generic Nullable< T > type).
/// </remarks>
/// <seealso cref="GetNullableType"/>
public static bool IsTypeNullable(Type TypeToTest)
{
// Abort if no type supplied
if (TypeToTest == null)
return false;
// If this is not a value type, it is a reference type, so it is automatically nullable
// (NOTE: All forms of Nullable<T> are value types)
if (!TypeToTest.IsValueType)
return true;
// Report whether TypeToTest is a form of the Nullable<> type
return TypeToTest.IsGenericType && TypeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
}
Trên đây IsTypeNullable thực hiện hoạt động như một nhà vô địch mọi thời gian, nhưng nó hơi dài dòng và chậm chạp trong dòng mã cuối cùng của nó. Phần mã sau giống như trên cho IsTypeNullable, ngoại trừ dòng mã cuối cùng đơn giản và nhanh hơn:
// Abort if no type supplied
if (TypeToTest == null)
return false;
// If this is not a value type, it is a reference type, so it is automatically nullable
// (NOTE: All forms of Nullable<T> are value types)
if (!TypeToTest.IsValueType)
return true;
// Report whether an underlying Type exists (if it does, TypeToTest is a nullable Type)
return Nullable.GetUnderlyingType(TypeToTest) != null;
Tận hưởng!
Đánh dấu
P.S. - Giới thiệu về "vô hiệu"
Tôi nên lặp lại một tuyên bố về tính không có khả năng mà tôi đã thực hiện trong một bài đăng riêng biệt, áp dụng trực tiếp cho việc giải quyết đúng chủ đề này. Đó là, tôi tin rằng trọng tâm của cuộc thảo luận ở đây không phải là cách kiểm tra xem một đối tượng có phải là một kiểu Nullable chung hay không, mà là người ta có thể gán một giá trị null cho một đối tượng thuộc kiểu của nó. Nói cách khác, tôi nghĩ rằng chúng ta nên xác định xem một loại đối tượng là nullable, không cho dù đó là Nullable. Sự khác biệt là trong ngữ nghĩa, cụ thể là những lý do thực tế để xác định tính vô dụng, mà thường là tất cả những gì quan trọng. Trong một hệ thống sử dụng các đối tượng với các kiểu có thể chưa biết cho đến khi thời gian chạy (dịch vụ web, cuộc gọi từ xa, cơ sở dữ liệu, nguồn cấp dữ liệu, v.v.), yêu cầu chung là xác định xem có thể gán một giá trị null cho đối tượng hay không đối tượng có thể chứa một giá trị rỗng. Việc thực hiện các hoạt động như vậy đối với các kiểu không nullable có thể sẽ tạo ra các lỗi, thường là các ngoại lệ, rất tốn kém cả về các yêu cầu về hiệu suất và mã hóa. Để có cách tiếp cận được ưu tiên cao của chủ động tránh các vấn đề như vậy, cần xác định xem một đối tượng của một loại tùy ý có khả năng chứa một giá trị rỗng không; tức là, cho dù nó nói chung là 'vô giá trị'.
Trong một ý nghĩa rất thực tế và điển hình, tính không có trong thuật ngữ .NET không nhất thiết phải ngụ ý rằng Kiểu của đối tượng là một dạng Nullable. Trong nhiều trường hợp trên thực tế, các đối tượng có các kiểu tham chiếu, có thể chứa một giá trị null, và do đó tất cả đều không có giá trị; không cái nào trong số này có kiểu Nullable. Do đó, cho các mục đích thực tế trong hầu hết các kịch bản, việc thử nghiệm nên được thực hiện cho khái niệm chung về tính vô hiệu, so với khái niệm phụ thuộc vào thực thi của Nullable. Vì vậy, chúng ta không nên bị treo lên bằng cách chỉ tập trung vào loại .NET Nullable mà là kết hợp sự hiểu biết của chúng ta về các yêu cầu và hành vi của nó trong quá trình tập trung vào khái niệm thực tế về tính vô dụng.
Tốt! Đây là một giải pháp thực sự gọn gàng. – ljs
Câu trả lời hay! Chỉ cần những gì tôi đang tìm kiếm. –
Giải pháp mát. Điều gì về làm cho nó một phương pháp mở rộng trên Type chính nó? Có vẻ phù hợp trong tình huống này. –