Комментарии 11
Спасибо, я сам раньше думал, что конструктор по умолчанию запрещен в структурах, чтобы сохранялось правило «обнуления» вновь созданной структуры, про time penalty при создании массивов не думал.
Небольшой вопрос, если конструктор по-умолчанию все-таки определен в структуре, то default(StructType) будет его вызывать?
Небольшой вопрос, если конструктор по-умолчанию все-таки определен в структуре, то default(StructType) будет его вызывать?
Полезная статья. Хотелось бы еще заметить, что в структуре для инициализации все структуры можно вызвать не только конструктор по умолчанию :this(), но и заменить this внутри конструктора, как бы странно это не выглядело:
<code class="cs"> struct SomeStruct { private int _i; private double _d; public SomeStruct(int i) { this = new SomeStruct(); _i = i; // Поле _d инициализировано неявно! } } </code>
Более того, this в конструкторе структуры по сути является out параметром, если «дефолтный» конструктор не вызывается, и является ref-параметром, если «дефолтный» конструктор вызывается:
struct SomeStruct
{
private int _i;
private double _d;
public SomeStruct(int i)
: this()
{
// this в теле метода является ref SomeStruct
CreateOrUpdate(ref this);
}
public SomeStruct(double d)
{
// this() не вызывается, значит this является out SomeStruct:
Create(out this);
}
public static void CreateOrUpdate(ref SomeStruct str)
{
str = new SomeStruct();
}
public static void Create(out SomeStruct str)
{
str = new SomeStruct();
}
}
Как-то вы некоторые моменты сложно расписали. :) Одна из причин такого хитрого существующе/отсутствующего конструктора по умолчанию в частности ещё состоит в том, что структуры копируются при присвоении/передаче в качестве параметра. Что в принципе приводит с одной стороны к созданию нового объекта, с другой стороны конструктор вызываться не будет.
Как результат, наличие явного конструктора без параметров может привести к некоторым логическим проблемам.
Как результат, наличие явного конструктора без параметров может привести к некоторым логическим проблемам.
В С++, например, есть четкое разделение между конструктором компирования и конструктором по умолчанию и никаких логических проблем при этом нет.
Здесь есть такое же разделение, но при этом конструктор копирования «генерируется» не компилятором, а CLR. Так что я не вижу никакой связи между отсутствием конструкторов по умолчанию в языке C# и передачей по значению с автоматическим копированием всех полей структуры.
Здесь есть такое же разделение, но при этом конструктор копирования «генерируется» не компилятором, а CLR. Так что я не вижу никакой связи между отсутствием конструкторов по умолчанию в языке C# и передачей по значению с автоматическим копированием всех полей структуры.
конструктор копирования «генерируется» не компилятором, а CLR
Вот это как раз и есть принципиальная разница. CLR генерирует данный конструктор, но это её личное дело, как она это делает. Программист на C# без хаков повлиять на это никак не может.
Вот это как раз и есть принципиальная разница. CLR генерирует данный конструктор, но это её личное дело, как она это делает. Программист на C# без хаков повлиять на это никак не может.
Я так и не понял, какая связь между конструктором по умолчанию и процессом копирования?
Конструктор по умолчанию устанавливает исходный вариант создаваемому объекту, конструктор копирования делает побитовую (как в случае структур) копию объекта, что автоматически сохраняет его инвариант.
При копировании не должен вызываться конструктор по умолчанию, этого не происходит в том же С++, и этого не происходит в .NET при бинарной или DataContract десериализации объекта. Это нормальное и ожидаемое поведение.
Еще раз: к каким логическим проблемам приведет наличие явного конструктора без параметров в контексте передачи структур по значению и почему его можно создать в IL-е?
Конструктор по умолчанию устанавливает исходный вариант создаваемому объекту, конструктор копирования делает побитовую (как в случае структур) копию объекта, что автоматически сохраняет его инвариант.
При копировании не должен вызываться конструктор по умолчанию, этого не происходит в том же С++, и этого не происходит в .NET при бинарной или DataContract десериализации объекта. Это нормальное и ожидаемое поведение.
Еще раз: к каким логическим проблемам приведет наличие явного конструктора без параметров в контексте передачи структур по значению и почему его можно создать в IL-е?
этого не происходит в .NET при бинарной или DataContract десериализации объекта. Это нормальное и ожидаемое поведение.
Там можно рулить всякими ISerializable и .ctor(SerializationInfo info, StreamingContext context), т.е. получить вызов конструктора или заменяющего его метода.
к каким логическим проблемам приведет наличие явного конструктора без параметров в контексте передачи структур по значению
Проблемы могут быть в том, что он как раз не вызывается при создании копии объекта. Т.е. наличие некоторой инициализации в конструкторе по умолчанию может привести к ошибкам при отсутствии его вызова. В C# в этом месте решили явно ограничить поведение ради более стабильного поведения.
почему его можно создать в IL-е
Потому что IL гораздо функциональнее чем C#, и в других языках могут быть совершенно другие механизмы работы со структурами.
Там можно рулить всякими ISerializable и .ctor(SerializationInfo info, StreamingContext context), т.е. получить вызов конструктора или заменяющего его метода.
к каким логическим проблемам приведет наличие явного конструктора без параметров в контексте передачи структур по значению
Проблемы могут быть в том, что он как раз не вызывается при создании копии объекта. Т.е. наличие некоторой инициализации в конструкторе по умолчанию может привести к ошибкам при отсутствии его вызова. В C# в этом месте решили явно ограничить поведение ради более стабильного поведения.
почему его можно создать в IL-е
Потому что IL гораздо функциональнее чем C#, и в других языках могут быть совершенно другие механизмы работы со структурами.
Кстати, на на конструктор копирования структуры я даже не знаю, как с хаками повлиять. Разве что через CLR Profiling API, но даже в этом я не очень уверен.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Структуры и конструкторы по умолчанию