предотвратить перезапись в неявном операторе - PullRequest
0 голосов
/ 11 декабря 2011

У меня есть небольшой класс, давайте назовем uomvalue, который содержит UOM и поле Value.

У меня есть неявный оператор, который при прямом применении преобразует значение типа double в поле Value.

Так что, если я использую его «обычным» способом, все в порядке:

obj.UOM = "ft"; 
obj.Value = 123.4; //normal assignment

Моя проблема в том, что когда я назначаю с помощью неявного оператора:

obj = 123.4; //impl op assignement

... весь объект заменен, и любое присвоение, которое я, возможно, уже сделал для UOM, потеряно.

Это может попасть в категорию «тупой вопрос», потому что я действительно не тратил время на то, чтобы это выяснить, но есть простой способ сделать это, где я могу сохранить старое значение для UOM, когдаимпл.соч.используется?

Ответы [ 3 ]

3 голосов
/ 11 декабря 2011

Самый простой ответ: не иметь неявного преобразования из double.Такие неявные преобразования почти , на мой взгляд, всегда плохая идея.(Существуют исключения, но это не похоже на то, что это один из них.)

Мне кажется, что неявные преобразования также больше подходят для неизменяемых типов, где описываемая вами ситуация просто может 'т происходит.Мне кажется, что ваш код определенно был бы яснее без неявного преобразования.Например:

obj = SomeClass.FromDouble(123.4);

теперь очевидно с точки зрения того, что он делает.

И нет, вы не можете написать неявный оператор, который пытается сохранить существующее значение.В конце концов, все преобразования происходят перед присваиванием - ничего в выражении 123.4 ничего не знает о obj ... поэтому вам нужно было бы заставить сам оператор присваивания знать, что он должен использовать некоторую часть значения переменнойкоторый собирается , который будет назначен как часть разработки значения от до .Это становится проблематичным, когда не такого значения заранее.

Все это усложняется: откажитесь от преобразования:)

3 голосов
/ 11 декабря 2011

Избавьтесь от неявного приведения.

Ваше неявное приведение уничтожает информацию (а именно, поле UOM).
Неявные преобразования всегда должны сохранять всю информацию в исходном объекте.

Если целевой тип уже исходного типа, используйте явное приведение.

Вот почему uint имеет неявное приведение к double, но не к int.


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

2 голосов
/ 12 декабря 2011

Я помню учителя начальной школы, который отвечал на любой ответ, который пропускал единицу при необходимости, спрашивая «Что? Овца? Метры? Фунты? Годы?».

У вас есть класс, которыйимел в виду получить ответ на этот вопрос, и неявный оператор удаляет его.Если вы делаете:

x = 6.0

Вы говорите: «х теперь равен 6,0».Не «х теперь равен 6,0 - это те его аспекты, которые являются числовыми и неизменными в других отношениях», а просто «х теперь равен 6,0»

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

Другой путь - это другой вопрос.Если мы сделали:

UnitMeasure um = new UnitMeasure(6.0, Units.Meter);
double d = (double)um;

Тогда для вызывающего кода немного понятнее то, что когда мы назначаем 6.0meters для double, теперь double содержит 6.0.Я бы по-прежнему имел это явное, а не неявное (оно теряет информацию), и некоторые из них были бы достаточно осторожны с переопределениями приведения, чтобы все еще избегать его (в любом случае, есть хорошие аргументы), но по крайней мере это что-то значит.В конце концов, вы пишете код для людей и машин.Если вы не пишете что-то значимое или, что еще хуже, заставляете других писать что-то неважное, ваш дизайн может быть улучшен, и «эта комбинация числа и единицы равна 6» не имеет смысла.


Кроме того, причина, по которой неявные операторы (и явные операторы в этом отношении) перезаписывают, как они делают, заключается в том, что это именно то, для чего они.(int)3.2 создает новый int.(double)76 создает новый дубль.

Нет разницы между:

obj = 123.4;

И

UnitMeasure temp = new UnitMeasure(123.4);
obj = temp;

Как это может не перезаписать объект?

Единственными формами приведений, которые не создают новый объект, являются повышающие и понижающие значения, которые изменяют способ использования объекта, а не объекта:

string s = "abc";
object o = s;//implicit - but s was already an object!
string s2 = (string)o;//explicit - but o was already a string! (and it would throw otherwise).

Эти формы не изменяют некоторые части объекта, потому что они не изменяют любую часть объекта.

В конце дня вы спрашиваете, как получитьнеявное приведение, которое не ведет себя как неявное приведение.К счастью, вы не можете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...