2010-09-29 33 views
8

Có gì không ổn với việc sử dụng một nhà điều hành ngầm như sau:điều hành ngầm trên các loại generic

//linqpad c# program example 
void Main() 
{ 
    var testObject = new MyClass<int>() { Value = 1 }; 

    var add = 10 + testObject; //implicit conversion to int here 
    add.Dump(); // 11 
} 

class MyClass<T> 
{ 
    public T Value { get; set; } 
    public static implicit operator T (MyClass<T> myClassToConvert) 
    { 
     return myClassToConvert.Value; 
    } 
} 

Tôi đã suy nghĩ tôi có thể điều trị như thể hiện của đối tượng như một loại giá trị theo cách này, nhưng nhìn thấy như tôi đã không bao giờ nhìn thấy một ví dụ về điều này tôi nghĩ có lẽ có một lý do không để làm một cái gì đó như thế này mà ai đó có thể chỉ ra? Trong mã thực tế của tôi, tôi đã nghĩ đến việc làm điều này như là một phần của lớp trừu tượng dữ liệu, để tôi có thể trả về các đối tượng với thông tin mô tả dữ liệu cơ bản, nhưng cho phép mã logic coi nó là một kiểu giá trị. cần phải biết là giá trị, và đồng thời giữ cho nó tốt đẹp và an toàn với các loại thuốc generic.

Trả lời

10

Nếu tất cả những điều sau đây là đúng:

  • tất cả giá trị có thể của kiểu MyClass<T> của bạn (bao gồm cả null nếu nó không phải là một kiểu giá trị!) Bản đồ đến một giá trị hợp lệ T

  • toán tử ngầm không bao giờ ném (thậm chí không cho null!)

  • đồng ngầm nversion có ý nghĩa ngữ nghĩa và không gây nhầm lẫn cho lập trình viên khách hàng

thì không có gì sai với điều này. Tất nhiên bạn có thể thực hiện bất kỳ điều nào trong số ba điều này, nhưng nó sẽ là thiết kế tồi. Đặc biệt, một toán tử ngầm mà ném có thể rất khó gỡ lỗi vì nơi nó được gọi không nói rằng nó đang được gọi.

Ví dụ: xem xét rằng T? không có chuyển đổi ẩn thành T (trong đó, tất nhiên, T là loại giá trị). Nếu có một toán tử ngầm như vậy, nó sẽ phải ném khi T? là null, vì không có giá trị rõ ràng để chuyển đổi null thành điều đó có ý nghĩa đối với bất kỳ loại giá trị nào T.


Hãy để tôi đưa ra một ví dụ mà tôi đã gặp rắc rối gỡ rối một vấn đề mà các nhà điều hành ngầm ném:

public string Foo() 
{ 
    return some_condition ? GetSomething() : null; 
} 

Ở đây, GetSomething trở một cái gì đó của một loại tôi đã viết trong đó có một chuyển đổi ngầm người dùng định nghĩa đến string. Tôi đã thực hiện hoàn toàn chắc chắn rằng GetSomething không bao giờ có thể trả lại null, nhưng tôi đã nhận được NullReferenceException! Tại sao? Bởi vì đoạn code trên là không tương đương với

return some_condition ? (string)GetSomething() : (string)null; 

nhưng để

return (string)(some_condition ? GetSomething() : (Something)null); 

Bây giờ bạn có thể xem nơi null đến từ!

+0

Tôi không chắc rằng tôi hiểu mối quan tâm xung quanh các loại nullable ... Dường như với tôi rằng nếu bạn có n = new MyClass () {Value = null}; và mã tiêu thụ đã cố gắng làm một cái gì đó như int i = n; và nó sẽ ném cùng một ngoại lệ mà bất kỳ diễn viên xấu nào, không có gì đặc biệt về loại nullable ở đây phải không? – asawyer

+0

@asawyer: Đó chỉ là một ví dụ. Hãy tưởng tượng rằng không có 'T?' Và * bạn * đã phải thực hiện một 'Nullable ' của riêng bạn. Bạn có chuyển nó thành 'T' không? Câu trả lời của tôi giải thích lý do tại sao bạn không nên, và tại sao * real * 'T?' Thì không. – Timwi

+0

Tôi thấy bây giờ, đó là những loại mối quan tâm đã nhắc câu hỏi ở nơi đầu tiên. Có vẻ như tôi nên được chấp thuận, nhưng rất thận trọng. – asawyer

1

Đó là một mô hình tuyệt vời. Chỉ cần nhớ rằng để sử dụng biến này làm biến số T, bạn phải truyền một cách rõ ràng là T hoặc gán nó cho một biến loại T. Dàn diễn viên sẽ diễn ra tự động trong các cuộc gọi phương thức và những thứ khác (chẳng hạn như ví dụ bổ sung của bạn) lấy số T.

Implicit conversion without assignment?

+0

Điều đó không đúng. – Timwi

+0

@Timwi, bạn có chắc chắn không? 'MyClass myClass', tại thời điểm này,' myClass. * 'Sẽ chỉ giải quyết các thành viên trên' MyClass ', không phải trên' T'. Bạn sẽ phải làm như arootbeer đề cập, và làm '((T) myClass). *' Để truy cập vào bất kỳ thành viên trên 'T' chính nó. –

+0

Tôi đã hỏi câu hỏi này chỉ vài ngày trước. http://stackoverflow.com/questions/3703555/implicit-conversion-without-assignment – arootbeer

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