2008-11-15 37 views
29

Không giống như C++, trong C# bạn không thể quá tải toán tử gán.Có cách giải quyết nào để quá tải toán tử gán trong C# không?

Tôi đang làm một lớp Số tùy chỉnh cho phép tính số học với số lượng rất lớn và tôi muốn nó có giao diện của các kiểu số được tích hợp như int, decimal, v.v. Tôi đã quá tải toán tử số học, nhưng việc chuyển nhượng vẫn ...

Dưới đây là một ví dụ:

Number a = new Number(55); 
Number b = a; //I want to copy the value, not the reference 

có một cách giải quyết cho vấn đề đó?

+2

Giải thích vấn đề này (tại sao bạn cần nó). – Shog9

+0

Xin lỗi, có lẽ tôi nên cụ thể hơn. Tôi đang làm một lớp Số tùy chỉnh cho phép toán số học với số lượng rất lớn và tôi muốn nó có giao diện của các kiểu số được tích hợp như int, decimal, v.v. Tôi đã quá tải toán tử số học, nhưng nhiệm vụ còn lại ... –

+0

Cảm ơn - tôi đã thêm nhận xét của bạn vào chính câu hỏi đó. – Shog9

Trả lời

26

Vẫn chưa rõ ràng với tôi rằng bạn thực sự cần điều này. Hoặc:

  • Loại số của bạn phải là cấu trúc (có thể xảy ra - số là ví dụ phổ biến nhất của cấu trúc). Lưu ý rằng tất cả các loại bạn muốn loại của bạn để hành động như (int, thập phân vv) là cấu trúc.

hay:

  • kiểu dữ liệu Number của bạn nên được bất biến, làm cho mọi hoạt động đột biến trở lại một ví dụ mới, trong trường hợp này bạn không cần những dữ liệu được sao chép trên phân anyway. (Trên thực tế, kiểu của bạn nên không thay đổi dù đó có phải là cấu trúc hay không. Cấu trúc có thể thay đổi là điều ác, và một số chắc chắn không nên là một kiểu tham chiếu có thể thay đổi được.)
+0

Vâng, có lẽ ý tưởng cấu trúc là tốt. Và tôi thích lựa chọn bất biến - nó được đề xuất trong một câu trả lời khác. Cảm ơn, tôi sẽ cố gắng những gì bạn đề xuất. –

+1

Cấu trúc có thể thay đổi có thể là điều ác nhưng nhóm C# nghĩ rằng chúng ổn đối với các Điều tra viên. Tôi nghĩ rằng nó chính xác hơn để nói nó như một quy tắc chung. –

+3

Tính không ổn định không phải là điều xấu, nếu bạn có thể ngăn chia sẻ đối tượng. Điều này có thể được thực hiện bằng cách thực hiện các kiểu tuyến tính yêu cầu một số dạng quá tải gán. http://en.wikipedia.org/wiki/Linear_type_system. – cdiggins

6

Bạn sẽ không thể làm việc xung quanh nó có giao diện C++, vì a = b; có ngữ nghĩa khác trong C++ so với C#. Trong C#, a = b; làm cho một điểm đến cùng một đối tượng như b. Trong C++, a = b thay đổi nội dung của a. Cả hai đều có thăng trầm. Giống như bạn làm

MyType * a = new MyType(); 
MyType * b = new MyType(); 
a = b; /* only exchange pointers. will not change any content */ 

Trong C++ (nó sẽ mất tham chiếu đến đối tượng đầu tiên và tạo rò rỉ bộ nhớ. Nhưng hãy bỏ qua ở đây). Bạn không thể quá tải toán tử gán trong C++ cho điều đó.

Cách giải quyết rất dễ dàng:

MyType a = new MyType(); 
MyType b = new MyType(); 

// instead of a = b 
a.Assign(b); 

Disclaimer: Tôi không phải là một nhà phát triển C#

Bạn có thể tạo một ghi-chỉ-bất động sản như thế này. sau đó làm a.Self = b; ở trên.

public MyType Self { 
    set { 
     /* copy content of value to this */ 
     this.Assign(value); 
    } 
} 

Bây giờ, đây là không phải. Vì nó vi phạm nguyên tắc ít nhất là bất ngờ (POLS). Người ta sẽ không mong đợi một sự thay đổi nếu người ta làm a.Self = b;

+0

Có lẽ tôi có thể làm theo cách đó.Nhưng ý tôi là - một giải pháp mang lại cho tôi cái nhìn và cảm nhận thực sự về quá tải của nhà điều hành chuyển nhượng, vì vậy tôi có nghĩa là: MyType a = new MyType(); MyType b = new MyType(); a = b; và nó thực hiện một số logic gán tùy chỉnh. –

+0

Mô tả lý do tại sao nó không hoạt động là phát hiện tại chỗ. Như bạn đã đề xuất, mặc dù, ý tưởng Tự sở hữu không tốt như vậy, – Charlie

+0

"Trong C++, a = b thay đổi nội dung của a." - đó không hoàn toàn chính xác. nó phụ thuộc vào việc a và b là con trỏ hay không. a = b có thể làm cho một điểm đến b hoặc nó có thể gọi = quá tải của bạn và sao chép nội dung vào a. – MickyD

3

Thay vì tạo bản sao dữ liệu khi chuyển tham chiếu, bạn có thể làm cho lớp không thay đổi. Khi lớp là bất biến có nhiều tham chiếu đến nó không phải là một vấn đề vì nó không thể thay đổi.

Các hoạt động thay đổi dữ liệu dĩ nhiên sẽ trả về các phiên bản mới.

+0

Bây giờ đó là một ý tưởng tốt! Cảm ơn, tôi sẽ thử nó! –

42

bạn có thể sử dụng từ khóa 'ngầm' để tạo ra một tình trạng quá tải cho các công việc:

Giả sử bạn có một loại giống như Foo, mà bạn cảm thấy là ngầm convertable từ một chuỗi. Bạn sẽ viết phương pháp tĩnh sau trong lớp Foo của bạn:

public static implicit operator Foo(string normalString) 
{ 
    //write your code here to go from string to Foo and return the new Foo. 
} 

Sau khi làm điều đó, sau đó bạn có thể sử dụng sau trong mã của bạn:

Foo x = "whatever"; 
+2

Thật tuyệt, điều này sẽ trả lời một câu hỏi mà tôi yêu cầu;) –

+3

Điều đó không chỉ hoạt động nếu bạn đang cố gán một kiểu này cho loại khác? Đó là một diễn viên tiềm ẩn, sau khi tất cả. Tôi không nghĩ rằng sẽ giúp nếu bạn muốn gán 'Số' cho' Số'. –

+0

@ Jonathan Wood - Đó chính xác là những gì tôi đang tìm kiếm! Nhiều đánh giá cao! –

2

Một bài trước đề nghị này:

nhà điều hành ngầm tạm thời công khai Foo (string normalString) {}

tôi đã cố gắng tiếp cận này ... nhưng để làm cho nó làm việc bạn cần điều này:

công điều hành ngầm tĩnh Foo (Foo gốc) {}

và trình biên dịch sẽ không cho phép bạn có một chức năng chuyển đổi ngầm từ loại chính xác của bạn, cũng không phải từ bất kỳ loại cơ sở nào của chính bạn. Điều đó có ý nghĩa vì nó sẽ là một cách backdoor của việc ghi đè toán tử gán, mà C# không muốn cho phép.

+0

"Từ khóa ngầm được sử dụng để khai báo toán tử chuyển đổi loại người dùng xác định tiềm ẩn. Sử dụng toán tử này để bật chuyển đổi ngầm định giữa loại do người dùng xác định và loại khác, ..." - MSDN – MickyD

0

Đây là một giải pháp mà làm việc cho bản thân mình:

public class MyTestClass 
{ 
    private int a; 
    private string str; 

    public MyTestClass() 
    { 
     a = 0; 
     str = null; 
    } 

    public MyTestClass(int a, string str) 
    { 
     this.a = a; 
     this.str = str; 
    } 

    public MyTestClass Clone 
    { 
     get 
     { 
     return new MyTestClass(this.a, this.str); 
     } 
    } 
} 

Một nơi nào đó khác trong các mã:

MyTestClass test1 = new MyTestClass(5, "Cat"); 
MyTestClass test2 = test1.Clone; 
Các vấn đề liên quan