2012-04-30 11 views
15

Mam typ reprezentujący typ liczby. W tym przypadku pracuję z megawatami, więc stworzyłem typ o nazwie Megawatt. Chciałbym móc pracować z tymi megawatami, tak jakbym był typu Int, Double lub dowolnego typu C#. czy to możliwe? Jeśli tak, jak to zrobić?Jak dodać lub odjąć dwie instancje tej samej klasy/typu?

Przykład:

public class Megawatt{ 
    public double Value { get; set; } 
} 

Chcę móc to zrobić:

var startOfDay = new Megawatts{value=100}; 
var endOfDay = new Megawatts{value=65}; 
Megawatt result = startOfDay - endOfDay; 

Jest to możliwe z DateTime ... można odjąć jeden od drugiego DateTime i dostać Okres. Mam nadzieję, że zrobię coś podobnego.

+1

Zobacz także http://stackoverflow.com/questions/348853/jednostki-zakresu-in-c-sharp-almost –

+0

Powinieneś użyć operatora Przeciążenie –

Odpowiedz

29

Oprócz dobrych odpowiedzi opublikowanych do tej pory: należy dokonać typ niezmienna struct zamiast typu wartości zmienny. Jest to dokładnie taka praca, do której zostały zaprojektowane niezmienne typy wartości.

struct Megawatt 
{ 
    private double Value { get; private set; } 
    public Megawatt(double value) : this() 
    { 
     this.Value = value; 
    } 
    public static Megawatt operator +(Megawatt x, Megawatt y) 
    { 
     return new Megawatt(x.Value + y.Value); 
    } 
    public static Megawatt operator -(Megawatt x, Megawatt y) 
    { 
     return new Megawatt(x.Value - y.Value); 
    } 
    // unary minus 
    public static Megawatt operator -(Megawatt x) 
    { 
     return new Megawatt(-x.Value); 
    } 
    public static Megawatt operator *(Megawatt x, double y) 
    { 
     return new Megawatt(x.Value * y); 
    } 
    public static Megawatt operator *(double x, Megawatt y) 
    { 
     return new Megawatt(x * y.Value); 
    } 
} 

I tak dalej. Zauważ, że możesz dodać dwa megawaty, ale nie możesz pomnożyć dwóch megawatów; możesz tylko mnożyć megawaty przez duble.

Można również dodać więcej typów obciążonych jednostkami. Na przykład możesz utworzyć MegawattHour typu i godzinę typu, a następnie powiedzieć, że Megawatt razy Godzina daje MegawattHour. Można również powiedzieć, że istnieje inny typ Joule i istnieje niejawne przejście z MegawattHour do Joule.

Istnieje wiele języków programowania, które obsługują tego rodzaju operacje z mniejszą ilością gadżetów niż C#; jeśli robisz dużo tego typu rzeczy, możesz zajrzeć do F #.

+1

Jestem trochę ciekawy tego, dlaczego chcielibyśmy, aby typ Megawatt był niezmienny? – Julien

+7

@Julien: Zawsze chcesz, aby * wartości * były niezmienne. Zastanów się nad reaktorem; ma właściwość "wynik". Oczywiście, dane wyjściowe mogą się zmienić. Załóżmy, że masz dwa reaktory, a moc wyjściowa obu wynosi 12 megawatów. Aby zmienić moc wyjściową reaktora na 13, zmienia się * wynik * reaktora jeden na 13. Nie mówisz "hej 12, wartość 12 to teraz 13", ponieważ to zmieniłoby wartość wyjść * obu * reaktory. –

+0

Dobrze. Zauważyłem również, że twoja Megawatt jest strukturą, która ma więcej sensu niż klasa dla tego użycia ... Czy wiesz coś o obciążeniu podczas używania tego rodzaju struktur, a nie tylko podwójnego? – Julien

2

Nazywa się to przeciążeniem operatora. Proponuję przeczytać ten artykuł:

http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

Jest to poradnik na temat procesu. Zasadniczo zmieniasz znaczenie operatora - dla tych typów.

Jako przykład (skradziony z linku)

public static Megawatt operator -(Megawatt c1, Megawatt c2) 
{ 
    // do whatever you want here 
} 

I w ten sposób Twój znak minus może teraz odejmowanie megawatów

Można to zrobić dla każdego typu lub kombinacji typów. Możesz nawet powrócić jeszcze trzeci typ, jeśli chcesz. Wiele języków obsługuje tę koncepcję i jest bardzo przydatne.

10

trzeba napisać własną przeciążanie operatorów:

próbki:

public static Megawatt operator +(Megawatt c1, Megawatt c2) 
    { 
     return new Megawatt(c1.value+ c2.value); 
    } 
+0

Gdzie ta metoda powinna żyć? –

+0

w klasie Megawatta –

+0

Świetnie! To działało idealnie. –

1

Rozszerzona odpowiedź: Przeciążenie operatora to na pewno sposób w tym przypadku. Przeciążanie operatorów jest świetną opcją w języku C#, która zapewnia wygodę operatorom zamiast metod w klasie.

Podczas przeciążania operatora, takiego jak +, odpowiedni operator przypisania złożonego jest również przeciążany, np.+=

Jak można sobie wyobrazić, z ich używania, przeciążenia operatora musi być static i użyć słowa kluczowego operator jak w @ odpowiedź RoyiNamir użytkownika.

Wystarczy rozwinąć odpowiedź następujące binarne operatory porównania, oprócz operatorów matematycznych, może być przeciążony tylko w parach:

  1. == i !=
  2. > i <
  3. >= i <=

W zakresie zalecanego projektowania kodu jon, tak jak @RoyiNamir powiedział, przeciążenie operatora powinno istnieć w klasie, że przeciążają operatorów.

0

Tworzenie własnych typów to dobry pomysł; Zapobiega problemom lądownika Mars, gdzie dodajesz kilogramy i funty. Sugeruję jednak, aby je tworzyć, a nie klasy, ponieważ spowoduje to, że staną się niezmienne i usuwają potencjał inicjowania wartości pustych. Ponadto, upewnij value prywatny, dzięki czemu można zrobić rzeczy jak:

var startOfDay = new Megawatts(100); 
var endOfDay = new Megawatts(65); 
Megawatt result = startOfDay - endOfDay; 

Należy również rozważyć wdrożenie IComparable<>, IEquatable<>, operatory konwersji, i tak dalej. Umożliwi to przeprowadzanie porównań i tworzenie zbiorów, s. Megawatt.

Wykonanie wszystkich tych czynności wymaga dużo pracy; skonsultuj się z C# Canonical Forms.

+0

"Sugeruję, aby były to konstrukcje, a nie klasy, ponieważ to uczyni je niezmiennymi": oznacza to, że konstrukcje są koniecznie niezmienne, a to nie jest prawdą. – phoog

Powiązane problemy