2010-12-27 6 views
44

Я знаю, что оператор = не может быть перегружен, но должна быть способом сделать то, что я хочу здесь:Перегрузка оператора присваивания в C#

Я просто создание классов для представления количественных единиц, так как я я делаю немного физики. По-видимому, я не могу просто наследовать от примитива, но я хочу, чтобы мои классы вели себя точно так же, как примитивы - я просто хочу, чтобы они набрали по-другому.

Так что я был бы в состоянии идти,

Velocity ms = 0; 
ms = 17.4; 
ms += 9.8; 

т.д.

Я не знаю, как это сделать. Я решил, что просто напишу несколько таких классов:

class Power 
{ 
    private Double Value { get; set; } 

    //operator overloads for +, -, /, *, =, etc 
} 

Но, по-видимому, я не могу перегрузить оператор присваивания. Есть ли способ получить такое поведение?

+0

Вы просмотрели функцию единиц измерения F #? он знает стандартные (ISO) единицы, такие как M, KG и M/S, и он также может рассчитывать с помощью единиц. –

+1

абсолютно, я использую его сейчас. Он не знает единицы ИСО, вы сами определяете единицы, например '[] тип m; [] type s', а затем использовать такие вещи, как 'let a = 9.8 /4.3 ', который дает 'val a: float = 2.279069767' –

+1

К сожалению, я хотел сказать единицы СИ, которые предопределены в Microsoft. FSharp.Math.SI'. См.: Http://blogs.msdn.com/b/andrewkennedy/archive/2008/09/02/units-of-measure-in-f-part-two-unit-conversions.aspx –

ответ

67

Это звучит, как вы должны использовать -структуру, а не класс ... а затем создать неявный оператор преобразования, а также различные операторы для того и т.д.

Вот некоторые примеры код:

public struct Velocity 
{ 
    private readonly double value; 

    public Velocity(double value) 
    { 
     this.value = value; 
    } 

    public static implicit operator Velocity(double value) 
    { 
     return new Velocity(value); 
    } 

    public static Velocity operator +(Velocity first, Velocity second) 
    { 
     return new Velocity(first.value + second.value); 
    } 

    public static Velocity operator -(Velocity first, Velocity second) 
    { 
     return new Velocity(first.value - second.value); 
    } 

    // TODO: Overload == and !=, implement IEquatable<T>, override 
    // Equals(object), GetHashCode and ToStrin 
} 

class Test 
{ 
    static void Main() 
    { 
     Velocity ms = 0; 
     ms = 17.4; 
     // The statement below will perform a conversion of 9.8 to Velocity, 
     // then call +(Velocity, Velocity) 
     ms += 9.8; 
    } 
} 

(в качестве побочной записки ... Я не понимаю, как это на самом деле представляет собой скорость, точно так же, что нужно направление, а также величины .)

+3

Отлично! Благодарю. Также ... ты прав. Очевидно, что мой физик-профессор не смог сильно вбить векторы в мой мозг :) –

+1

Есть ли причина, по которой это не может быть класс? Я надеялся наследовать от класса ScalarUnit или VectorUnit, чтобы не повторять _everything_ для каждой единицы, и, по-видимому, структуры не могут наследовать –

+7

@Henk: Нет, * скорость * - это скаляр, но скорость имеет направление. См. Http://en.wikipedia.org/wiki/Velocity - «Это векторная физическая величина, для ее определения требуются как величина, так и направление». –

-9

Я думаю, что он не может быть перегружен, потому что все классы C# являются производными от Object, поэтому они являются в основном объектами, и когда вы используете операторы присваивания, вы в основном просто ссылаетесь на другой объект. С другой стороны, если вы используете структуру, то вам в основном нужна вся информация, поэтому, когда вы используете оператор =, все поля будут скопированы.

Так что я бы сказал, лицо его, и реализовать функцию под названием Copy() и вы должны быть хорошо :-)

+0

Как это отличается от других операторов? Как вы добавляете всю информацию двух объектов вместе? Я хочу назначить непосредственно внутреннему значению, а не переписывать весь объект –

+1

Я думаю, что он не может быть перегружен, потому что разработчики языка подумали, что это будет плохая идея.Нет никаких технических причин, по которым это невозможно сделать. –

+1

Нет, я думаю, что есть причина. Скажем, у вас есть объект a и объект b. Как только вы запустите оператор a = b, объект, на который был направлен a, фактически будет собирать мусор (потому что больше нет объекта, указывающего на него), так как будет реализовывать оператор присваивания здесь? С другой стороны, все другие операторы возвращают другой объект (например, a + b) или фактически изменяют текущий объект, когда он не будет потерян (т. Е. Собранный мусор) (например, a + = b). – Rafid

9

Вы можете создать неявные операторы преобразования. Существует page on MSDN с хорошим примером.

Это также хорошая идея сделать их неизменяемыми структурами. Именно это и есть «примитивы», и именно это делает невозможным унаследовать их. Вам нужна структура, потому что вы хотите семантику типа значения, а не семантику ссылочного типа. И вы хотите, чтобы они неизменны, потому что типы изменяемого значения как правило, являются bad idea.

Смежные вопросы