2010-02-02 33 views
8

Tôi muốn có thể kiểm tra xem giá trị có phải là giá trị mặc định cho loại giá trị của nó hay không. Lý tưởng nhất, tôi muốn nói:Kiểm tra giá trị mặc định bằng các loại chung

DoSomething<TValue>(TValue value) { 
    if (value == default(TValue)) { 
     ... 
    } 
} 

Tuy nhiên, trình biên dịch phàn nàn rằng nó không thể làm một so sánh == trên TValue và TValue. Đây là giải pháp tốt nhất mà tôi đã đưa ra cho đến thời điểm này:

DoSomething<TValue>(TValue value) { 
    if (value == null || value.Equals(default(TValue))) { 
     ... 
    } 
} 

Có cách nào thanh lịch/chính xác hơn để giải quyết vấn đề này không?

Trả lời

37
public bool EqualsDefaultValue<T>(T value) 
{ 
    return EqualityComparer<T>.Default.Equals(value, default(T)); 
} 
4

Ném trong ràng buộc lớp và nó sẽ hoạt động.

public void Test<T>(T instance) where T : class 
{ 
    if (instance == default(T)) 
    { 

    } 
} 

Hoặc nếu bạn chỉ muốn loại giá trị, bạn có thể thực hiện việc này.

public void Test<T>(T instance) where T : struct, IEquatable<T> 
{ 
    if (instance.Equals(default(T))) 
    { 

    } 
} 
+4

Nếu bạn ném vào ràng buộc 'lớp' bạn cũng có thể chỉ kiểm tra đối với 'null' ... –

+0

@Marc - Tôi biết, tại thời điểm này nó là một vấn đề sở thích. – ChaosPandion

+0

Tôi hy vọng sẽ làm công việc này cho bất kỳ loại nào, bao gồm cả giá trị và loại lớp. – StriplingWarrior

1

Vấn đề của bạn là một loại genric (không hạn chế) đã được "biên dịch được" cho bất kỳ loại. Vì không phải tất cả các loại đều có toán tử == nên mã của bạn sẽ không biên dịch.

Một cách để giải quyết vấn đề này là thêm ràng buộc lớp học vì mặc định sử dụng (TValue) sẽ gợi ý bạn muốn mã hoạt động với các loại khác. (Nếu không chỉ cần sử dụng null thay vì mặc định (TValue). Một giải pháp có thể là một cái gì đó tương tự như những gì Bryan Watts gợi ý

bool DoSomething<TValue>(TValue value) { 
    return EqualityComparer<TValue>.Default.Equals(value, default(TValue)); 
} 

hoặc bạn có thể bọc nó trong một phương pháp khuyến nông

bool IsDefault<TValue>(this TValue value) { 
    return EqualityComparer<TValue>.Default.Equals(value, default(TValue)); 
} 
0

Thêm vào câu trả lời được đăng ở đây, tôi nghĩ chúng tôi cũng nên có thể chỉ định nếu bạn muốn giá trị hoặc tham chiếu bình đẳng:

static public class MyGenericHelper 
{ 
    static public bool EqualsByValue<T>(T x, T y) 
    { 
     return EqualityComparer<T>.Default.Equals(x, y); 
    } 

    static public bool EqualsByReference<T>(T x, T y) 
    { 
     if (x is ValueType) return EqualityComparer<T>.Default.Equals(x, y) // avoids boxing 

     return Object.ReferenceEquals(x, y); 
    } 
} 

Tất cả chúng ta chỉ cần tạo và duy trì một tỷ h phương pháp elper như vậy không phải chúng ta: ->

+0

Có vẻ như 'typeof (T) .IsValueType' sẽ thích hợp hơn với' x là ValueType' cả về khả năng đọc và hiệu suất. Liệu tôi có sai? – StriplingWarrior

+1

Có lẽ khả năng đọc là một vấn đề của hương vị đôi khi. : -> ... 'x là ValueType' chỉ trực giác" cảm thấy nhanh hơn "đối với tôi, vì' typeof (T) .IsValueType' phải truy lục thể hiện 'Type' khá nặng và Reflector tiết lộ rằng' .IsValueType' property gọi một phương thức ảo được thực hiện trong 'RuntimeType' cuối cùng gọi một cái gì đó bên ngoài. Nhưng sau đó tôi là ai để phán xét, tôi không phải là người trong cuộc. Họ thậm chí có thể biên dịch xuống các hướng dẫn tương tự. Có lẽ đó là một câu hỏi hay. ;-) ... Hoặc bạn có thể tự mình thực hiện một số thử nghiệm hiệu suất nếu nó rất quan trọng. – herzmeister

+0

Nó không quan trọng, nhưng tôi tò mò, vì vậy tôi đã làm một bài kiểm tra nhanh và bạn đã đúng! 'x là ValueType' mất khoảng một phần ba. – StriplingWarrior

Các vấn đề liên quan