2012-01-19 22 views
9

Giả sử tôi có một cấu trúc chỉ với một lĩnh vực:Tôi có phải định nghĩa mọi toán tử đơn lẻ không?

public struct Angle 
{ 
    public static readonly double RadiansPerDegree = Math.PI/180; 

    private readonly double _degrees; 

    public Angle(double degrees) 
    { 
     _degrees = degrees; 
    } 

    public double Degrees 
    { 
     get { return _degrees; } 
    } 

    public double Radians 
    { 
     get { return _degrees * RadiansPerDegree; } 
    } 

    public static Angle FromDegrees(double value) 
    { 
     return new Angle(value); 
    } 

    public static Angle FromRadians(double value) 
    { 
     return new Angle(value/RadiansPerDegree); 
    } 
} 

này hoạt động tuyệt vời, cho đến khi tôi muốn làm những thứ như thế này:

var alpha = Angle.FromDegrees(90); 
var beta = Angle.FromDegrees(100); 
var inequality = alpha > beta; 
var sum = alpha + beta; 
var negation = -alpha; 
//etc. 

Vì vậy, tôi thực hiện IEquatable<in T>IComparable<in T>, nhưng điều đó vẫn không bật bất kỳ toán tử nào (thậm chí không ==, <, >=, v.v.).

Vì vậy, tôi đã bắt đầu cung cấp tình trạng quá tải của nhà điều hành.

Ví dụ:

public static Angle operator +(Angle a, Angle b) 
{ 
    return new Angle(a._degrees + b._degrees); 
} 

public static Angle operator -(Angle a) 
{ 
    return new Angle(-a._degrees); 
} 

public static bool operator >(Angle a, Angle b) 
{ 
    return a._degrees > b._degrees; 
} 

này làm việc, tuy nhiên, khi tôi nhìn vào tất cả các nhà khai thác tôi có thể hình dung quá tải (+, -, !, ~, ++, --, true, false, +, -, *, /, %, &, |, ^, <<, >>, ==, !=, <, >, <=, >=), tôi bắt đầu cảm thấy như có phải là một cách tốt hơn. Sau khi tất cả, cấu trúc chỉ chứa một trường, và trường đó là một kiểu giá trị.

Có cách nào để cho phép tất cả các nhà khai thác của double trong một lần phát không? Hay tôi thực sự phải loại bỏ mọi toán tử mà tôi có thể muốn hỗ trợ bằng tay?

(Thậm chí nếu tôi có hai hoặc ba lĩnh vực, tôi vẫn muốn để có thể thêm các nhà khai thác trong cùng một nhóm ...)

+3

Bạn có thể thêm phôi ngầm để (và có thể từ) loại 'double' để làm điều đó. Mặc dù, một cái gì đó trong đầu của tôi nói với tôi rằng đó có thể không phải là một ý tưởng tốt và có thể dẫn đến sự mơ hồ. –

+1

Nếu bạn thực sự làm điều này chỉ cho mức độ và chuyển đổi radian, tại sao không chỉ có một lớp MathHelper tĩnh thực hiện các tính năng đó và chỉ sử dụng gấp đôi thay vì tạo một lớp tái phát sinh một lớp khác với một tên khác? –

+0

@ Jeff Mercado, tôi nghĩ rằng một diễn viên tiềm ẩn có thể chỉ là những gì tôi đang tìm kiếm, thực sự. Bạn có cân nhắc chuyển đổi nhận xét của mình thành câu trả lời không? Ngoài ra, nếu có thực sự là một nhược điểm, tôi thực sự đánh giá cao nếu bạn có thể mở rộng trên đó một chút. Cảm ơn. – devuxer

Trả lời

12

Mấu chốt của các nhà khai thác quá tải là xác định làm thế nào để thêm để thao tác các đối tượng của một kiểu tùy chỉnh bằng cách sử dụng các toán tử đó, vì vậy nếu trường thứ hai của bạn là một mảng chuỗi, làm thế nào bạn mong đợi toán tử ++ được thực hiện tự động? Không có câu trả lời hợp lý, đặc biệt là vì chúng ta không biết bối cảnh của đối tượng hoặc cách sử dụng của nó, vì vậy câu trả lời là có, bạn phải tự mình quá tải các toán tử. Để ghi lại, nếu bạn thực sự chỉ cần một trường, và nó chỉ là gấp đôi, sau đó không sử dụng cấu trúc ở vị trí đầu tiên trừ khi bạn cần quá tải các toán tử để thực hiện một số hành động khác hơn là mặc định - đó là trường hợp rõ ràng về kỹ thuật quá mức!

+0

Ví dụ 'Góc' là một sự đơn giản hóa, nhưng mục tiêu của tôi là làm cho nó rất rõ ràng các đơn vị là gì, và để gói gọn sự chuyển đổi cần thiết giữa các đơn vị thành một loại duy nhất. Vì vậy, nếu tôi có một 'Góc', không có sự mơ hồ về đơn vị, tôi chỉ lấy bất cứ điều gì tôi cần. Những gì tôi đã nhận được tại với câu hỏi của tôi là, tôi muốn có một số cách để nói với trình biên dịch mà tôi muốn struct để cư xử như thể nó là lĩnh vực cơ bản cho tất cả các hoạt động. Đề xuất của @Jeff Mercado sử dụng các phôi ngầm * dường như * để thực hiện điều đó, nhưng dường như anh ta lo ngại rằng có thể có những hậu quả không mong muốn. – devuxer

+0

Ngay sau khi các loại là một cái gì đó phức tạp hơn so với những cái nguyên thủy sau đó bạn có thể thấy làm thế nào một hệ thống sẽ không thể tạo ra các hoạt động có ý nghĩa cho các dữ liệu trong câu hỏi. Ít nhất bạn biết bạn đang làm gì! Tôi muốn đề nghị có thể tạo ra một vĩ mô trong một IDE như Vim để tạo ra tất cả các nhà khai thác cho các cấu trúc của bạn nếu nó là một cái gì đó bạn sẽ làm nhiều hơn một lần. –

+0

Tôi nghĩ rằng trong tất cả các trường hợp tôi dự đoán cho dự án cụ thể này, tôi có thể chuyển đổi hoàn toàn toàn bộ loại thành một kiểu giá trị riêng cho mục đích thực hiện các hoạt động, nhưng nếu tôi gặp một điều phức tạp hơn, ý tưởng macro để tạo ra điều hành quá tải âm thanh tốt. – devuxer

0

Có, bạn phải xác định mọi toán tử mà bạn muốn sử dụng. Trình biên dịch không có cách nào để biết những gì bạn muốn mỗi toán tử thực hiện, ngoài các toán tử là âm của nhau (và thậm chí cả những toán tử này không nhất thiết phải rõ ràng, điều gì sẽ xảy ra nếu bạn muốn bắt chước hành vi rỗng chuẩn của SQL ở cả hai số ==!= sẽ trả về false khi so sánh với giá trị rỗng?).

0

Đối với hầu hết các trường hợp, tôi đồng ý với LaceySnr: nó không thực sự hiệu quả đối với bất kỳ toán tử nào trả lại đối tượng mới của bạn (ví dụ: +, * ect.). Đối với các bộ so sánh nó có thể làm việc (như trong đó có thể là một chú thích cho biết "sử dụng giá trị trả về của phương thức này để đứng cho đối tượng này khi được sử dụng trong tất cả các phép so sánh"), nhưng tôi không biết bất cứ thứ gì như thế.

Tôi không chắc chắn những hạn chế của chú thích là gì trong C#, nhưng có thể tạo ra điều đó (đối với toán tử trả về bool), trừ khi bạn định dùng nó rất nhiều Nó xứng đáng với thời gian của bạn. Có nói điều này, nếu bạn đã có một đối tượng mà đã chính xác một đối số vào constructor, và đối số đó là giá trị trả về của phương thức, nó sẽ có thể làm điều đó cho điều đó là tốt.

Tất nhiên để làm được điều này đòi hỏi phải có một số khá cực đoan đẳng cấp mày mò, mà tôi không thực sự trong một tình huống để đưa ra lời khuyên về ...

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