Два операнда (1 и 3) являются целыми числами, поэтому используется целочисленная арифметика (деление здесь). Объявление переменной результата как double просто приводит к возникновению неявного преобразования после деления .
Целочисленное разделение конечно возвращает истинный результат деления, округленный до нуля. Таким образом, результат 0.333...
округляется до 0. (Обратите внимание, что процессор фактически не делает никакого округления, но вы можете думать об этом так же).
Также обратите внимание, что если указаны оба операнда (числа) как плавающие; 3.0 и 1.0, или даже только first , то используется арифметика с плавающей запятой, дающая вам 0.333...
.
, Как Вы выбираете между реализацией объекта значения (канонический пример, являющийся адресом) как неизменный объект или структура?
я думаю, что Ваши опции являются неправильными. Неизменный объект и структура не являются противоположностями, и при этом они не единственные опции. Скорее у Вас есть четыре опции:
, я утверждаю, что в.NET, выбор по умолчанию должен быть изменяемый класс для представления логика и неизменный класс для представления объект . Я на самом деле склонен выбирать неизменные классы даже для логических реализаций, если вообще выполнимый. Структуры должны быть зарезервированы для маленьких типов, которые эмулируют семантику значения, например, пользовательское Date
тип, Complex
тип числа подобные объекты. Акцент здесь находится на небольшой , так как Вы не хотите копировать большие блобы данных, и косвенность через ссылки является на самом деле дешевой (таким образом, мы не получаем много при помощи структур). Я склонен делать структуры всегда неизменными (я не могу думать о единственном исключении в данный момент). Так как это лучше всего соответствует семантике типов внутренней ценности, за которыми я нахожу хорошим правилом следовать.
Существует несколько вещей рассмотреть:
структура А выделяется на стеке (обычно). Это - тип значения, так раздавание данных через методы может быть дорогостоящим, если это является слишком большим.
класс А выделяется на "куче". Это - ссылочный тип, так раздавание объекта через методы не является столь же дорогостоящим.
Обычно я использую структуры для неизменных объектов, которые не являются очень большими. Я только использую их, когда существует ограниченный объем данных, сохраненный в них, или я хочу неизменность. Пример DateTime
структура. Мне нравится думать, что, если мой объект не так легок как что-то как DateTime
, это, вероятно, не стоит использоваться в качестве структуры. Кроме того, если мой объект не имеет смысла, раздаваемого как тип значения (также как DateTime
), то не может быть полезно использовать в качестве структуры. Неизменность является ключевой здесь все же. Кроме того, я хочу подчеркнуть, что структуры не неизменны по умолчанию. Необходимо сделать их неизменными дизайном.
В 99% ситуаций я встречаюсь, класс является надлежащей вещью использовать. Я нахожу меня не необходимостью в неизменных классах очень часто. Более естественно для меня думать о классах как изменяемых в большинстве случаев.
Мне нравится использовать мысленный эксперимент:
этот объект имеет смысл, когда только пустого конструктора называют?
Редактирование в запрос Richard E
А хорошее использование struct
должно перенести примитивы и определить объем их к допустимым диапазонам.
, Например, вероятность имеет допустимый диапазон 0-1. Используя десятичное число для представления это везде подвержено ошибке и требует проверки в каждой точке использования.
Вместо этого можно перенести примитив с проверкой и другими полезными операциями. Это передает мысленный эксперимент, потому что большинство примитивов имеет естественные 0 состояний.
Вот использование в качестве примера struct
для представления вероятности:
public struct Probability : IEquatable<Probability>, IComparable<Probability>
{
public static bool operator ==(Probability x, Probability y)
{
return x.Equals(y);
}
public static bool operator !=(Probability x, Probability y)
{
return !(x == y);
}
public static bool operator >(Probability x, Probability y)
{
return x.CompareTo(y) > 0;
}
public static bool operator <(Probability x, Probability y)
{
return x.CompareTo(y) < 0;
}
public static Probability operator +(Probability x, Probability y)
{
return new Probability(x._value + y._value);
}
public static Probability operator -(Probability x, Probability y)
{
return new Probability(x._value - y._value);
}
private decimal _value;
public Probability(decimal value) : this()
{
if(value < 0 || value > 1)
{
throw new ArgumentOutOfRangeException("value");
}
_value = value;
}
public override bool Equals(object obj)
{
return obj is Probability && Equals((Probability) obj);
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public override string ToString()
{
return (_value * 100).ToString() + "%";
}
public bool Equals(Probability other)
{
return other._value.Equals(_value);
}
public int CompareTo(Probability other)
{
return _value.CompareTo(other._value);
}
public decimal ToDouble()
{
return _value;
}
public decimal WeightOutcome(double outcome)
{
return _value * outcome;
}
}
Факторы: конструкция, требования к памяти, упаковывая.
Обычно, ограничения конструктора для структур - никакие явные конструкторы без параметров, никакой base
конструкция - решает, должна ли структура использоваться вообще. Например, если конструктор без параметров должен не , инициализируют участников к значениям по умолчанию, используют неизменный объект.
, Если у Вас все еще есть выбор между этими двумя, выберите требования к памяти. Мелочи должны быть сохранены в структурах особенно, если Вы ожидаете много экземпляров.
, Что преимущество потеряно, когда экземпляры упаковываются (например, получил для анонимной функции или сохранил в неуниверсальном контейнере) - Вы даже начинаете платить дополнительный за упаковку.
<час>, Что является "маленьким", что такое "многие"?
издержки для объекта составляют 8 байтов (IIRC) в системе на 32 бита. Обратите внимание, что с несколькими сотнями из экземпляров, это может уже решить, работает ли внутренний цикл полностью в кэше или вызывает GC's. Если Вы ожидаете десятки тысяч экземпляров, это может быть различием между выполненным по сравнению с проверкой.
От этого POV, использование структур НЕ является преждевременной оптимизацией.
<час>Так, как эмпирические правила :
, Если большинство экземпляров упаковать, используйте неизменные объекты.
Иначе, для маленьких объектов, используют неизменный объект, только если конструкция структуры привела бы к неловкому интерфейсу , и Вы ожидаете не больше чем тысячи экземпляров.
В современном мире (я думаю C# 3.5) я не вижу потребность в структурах (РЕДАКТИРОВАНИЕ: Кроме в некоторых нишевых сценариях).
аргументы проструктуры, кажется, главным образом базируются вокруг воспринятых выигрышей в производительности. Я хотел бы видеть некоторые сравнительные тесты (которые копируют реальный сценарий), которые иллюстрируют это.
понятие использования структуры для "легких" структур данных кажется слишком субъективным на мой вкус. Когда данные прекращают быть легкими? Кроме того, чтобы добавление функциональности кодировало, который использует структуру, когда Вы решили бы изменить тот тип на класс?
Лично, я не могу вспомнить в прошлый раз, когда я использовал структуру в C#.
я предполагаю, что использование структуры в C# по причинам производительности является очевидным случаем Преждевременной Оптимизации <глоток> * глоток>
<глоток> *, если приложение не было представленной производительностью, и использование класса было идентифицировано как узкое место производительности глоток>
MSDN состояния:
тип структуры подходит для представления легких объектов, таких как Точка, Прямоугольник и Цвет. Хотя возможно представить точку как класс, структура более эффективна в некоторых сценариях. Например, если Вы объявите массив 1 000 Точечных объектов, то Вы выделите дополнительную память для ссылки на каждый объект. В этом случае структура является менее дорогой.
, Если Вам не нужна семантика ссылочного типа, класс, который меньше, чем 16 байтов могут быть более эффективно обработаны системой как структура.
В целом я не рекомендовал бы структуры для бизнес-объектов. В то время как Вы МОГЛИ БЫ получить небольшое количество производительности путем заголовка этого направления, поскольку Вы работаете на стеке, Вы заканчиваете тем, что ограничили себя до некоторой степени, и конструктор по умолчанию может быть проблемой в некоторых случаях.
я заявил бы, что это еще более обязательно, когда у Вас есть программное обеспечение, которое опубликовано.
Структуры хорошо для простых типов, который является, почему Вы видите, что Microsoft использует структуры для большинства типов данных. Подобным образом структуры хорошо для объектов, которые имеют смысл на стеке. Структура Точки, упомянутая в одном из ответов, является прекрасным примером.
, Как я решаю? Я обычно значение по умолчанию для возражения и если бы это, кажется, что-то, что извлекло бы выгоду из того, чтобы быть структурой, которая, как правило, будет довольно простым объектом, который только содержит простые типы, реализованные как структуры, затем я продумаю его и определю, имеет ли это смысл.
Вы упоминаете адрес как свой пример. Давайте исследуем один как класс.
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
Продумывают этот объект как структуру. В соображении считайте типы включенными в этом адресе "структура" при кодировании его тот путь. Вы видите что-нибудь, что не могло бы разработать способ, которым Вы хотите? Рассмотрите потенциальный выигрыш в производительности (т.е., есть ли один)?
Что является стоимостью копирования экземпляров, если передано значением.
, Если высокий, затем неизменная ссылка (класс) тип, иначе (структура) значения тип.
Как показывает опыт, размер структуры не должен превышать 16 байтов, в других отношениях передающих, это между методами может стать более дорогим, что передающий ссылки на объект, которые являются всего 4 байтами (на 32-разрядной машине) долго.
Другое беспокойство является конструктором по умолчанию. Структура всегда имеет значение по умолчанию (без параметров и общедоступный) конструктор, иначе операторы как
T[] array = new T[10]; // array with 10 values
не работали бы.
Дополнительно это является учтивым для структур, чтобы перезаписать ==
и эти !=
операторы и реализовать эти IEquatable<T>
интерфейс.
С точки зрения объектного моделирования я ценю структуры, потому что они позволяют мне использовать компилятор для объявления определенных параметров и полей как не допускающих NULL-значения. Конечно, без специальной семантики конструктора (как в Spec#), это только применимо к типам, которые имеют естественное 'нулевое' значение. (Следовательно Bryan Watt, 'хотя эксперимент' ответ.)
Структуры предназначены исключительно для опытных пользователей (вместе с out и ref).
Да, структуры могут дать отличную производительность при использовании ref, но вы должны видеть, какую память они используют. Кто контролирует память и т. Д.
Если вы не используете ref и out со структурами, они того не стоят, если вы ожидаете неприятных ошибок :-)