Как стать автором
Обновить

Комментарии 37

Круто облажались многие хабравчане :) Лишний раз напоминает о том, что гонору много, а знаний нет.

Хотя, справедливости ради, такие тонкости помнить необязательно. Лучше иметь хорошую голову, а нюансы всегда можно у рихтера подсмотреть.
Мне кажется, вполне адекватные вопросы, без каких-то глубочайших знаний язык. Поставил в тупик только вопрос с атрибутом Obsolete, который, как мне кажется, достаточно специфичным для повседневного использования. Ну и первый вариант ответа на первый вопрос — достаточно спорный.

В целом же мне кажется, что это не самый объективный опрос знаний C# на Хабре. Уверен, многие C и C++ разработчики тоже потыкали на кнопочки, многие решили наугад пощелкать, кто-то только начала изучать язык и т.д. Интересно было бы узнать, сколько реальных разработчиков участвовало в опросе, и как они отвечали.
Надо было в конце добавить вопрос «Вы действующий C# разработчик?» )
Часть вопросов сродни «Чем отличаются ref и out» из статьи про программиста в Нью-Йорке неподалеку.
Не видел ни одного проекта на C#, где была бы условная компиляция. Насчет obsolete — если подобный код используется в проекте, то логично, что ничего больше варнинга выдаваться не будет. А от них избавляются обычно в последнюю очередь. Unsafe код — специфичная вещь, и большинство C# разработчиков с ним не столкнутся (я сейчас говорю о нормальных проектах). Если надо — ответы на подобные вопросы легко найти.
В остальном вопросы довольно интересны.
Но, умение к месту применять паттерны и писать KISS код гораздо важнее вызубренного msdn имхо.
По поводу условной компиляции — winrt/winphone во все поля.

А вообще, да — найти ответы на эти вопросы действительно очень легко. Но тут дело в том, что попытка найти ответ на такие простые вопросы зачастую приводит к новым, уже более глубоким вопросам. Ну, банально — элементарный же вопрос про константы и ридонли поля. Вроде, разница понятна, а что из этого следует? Когда использовать одно, а когда другое? Постепенно углубляемся до обратной совместимости сборок — уже, вроде, и не так банально.

Или вот с упаковкой — автор статьи привел весьма скромное объяснение, но там всплывают и более серьезные вопросы, вроде, а какие, вообще, бывают преобразования типов и чем отличаются?

Короче говоря, не все очевидные вопросы имеют очевидную подоплеку.
Простите, вы случаем сборы военные в ЛО не проходили? «во все поля» — это довольная знаменитая фраза одного военного :).
Нет. Это, вроде, был довольно популярный мем когда-то.
Многие MVVM-фреймворки (например, Caliburn Micro) используют условную компиляцию для того, чтобы обеспечить портируемость на Silverlight \ WinRT \ Compact Framework. У нас на работе тоже используются — у продукта есть несколько редакций (basic, pro, corporate, trial) в зависимости от которых тот или иной код подключается или отключается, а также разные сервера для release \ debug сборок, адреса которых указываются также в директивах препроцессора.
Но, умение к месту применять паттерны и писать KISS код гораздо важнее вызубренного msdn имхо.

Дойче банк с вами явно не согласен.
Каким образом выражается несогласие? Собеседующие-неадекваты?
Выражается в том, что собеседующих абсолютно не интересует опыт работы или умение писать простой, красивый, понятный код. KISS, DRY, SOLID? Нет, не слышали. Расскажите лучше физический смысл второй производной. Ну и что, адекватный вопрос для разработчика игрового 3d-движка, скажет кто-нибудь? Вот только это собеседование на вакансию разработчика UI. Думаю, уместнее были бы вопросы по теории дусамфинга. Для тех, кто не читал:
xxx: седня узнал новое понятие из словаря разработчиков дойчебанка — заниматься дусамфингом
xxx: пример: — Чем этот чилавег у вас там занимается уже полгода? Ответ: Ай ду нот ноу, ду самфинг
xxx: есть целые команды, которые занимаются дусамфингом
xxx: это распространено
Надо думать, что отвечали не только C#/.Net программисты. Я, например, тоже внес свою лепту :), хотя на большинство вопросов ответил правильно/почти правильно.
Требую продолжения!
Ой… это я с VB уже напутал. Спасибо. Исправил.
Текст под картинкой тоже исправьте — теперь они расходятся.
К вопросу №1.
Стандарт ECMA-335 (.pdf), пункт I.8.9.5.
I.8.9.5 Class type definition

An explicit class definition:

  • Can optionally specify a method (called .cctor) to be called to initialize the type.

The semantics of when and what triggers execution of such type initialization methods, is as
follows:
  1. A type can have a type-initializer method, or not.
  2. A type can be specified as having a relaxed semantic for its type-initializer method
    (for convenience below, we call this relaxed semantic BeforeFieldInit).
  3. If marked BeforeFieldInit then the type’s initializer method is executed at, or
    sometime before
    , first access to any static field defined for that type.
  4. If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e.,
    is triggered by):
    1. first access to any static field of that type, or
    2. first invocation of any static method of that type, or
    3. first invocation of any instance or virtual method of that type if it is a value
      type or
    4. first invocation of any constructor for that type.
  5. Execution of any type's initializer method will not trigger automatic execution of
    any initializer methods defined by its base type, nor of any interfaces that the type
    implements.

For reference types, a constructor has to be called to create a non-null instance. Thus, for
reference types, the .cctor will be called before instance fields can be accessed and methods can
be called on non-null instances.

If a language wishes to provide more rigid behavior—e.g., type initialization automatically
triggers execution of base class’s initializers, in a top-to-bottom order—then it can do so by
either:
...
  • by making explicit calls to
    System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor

Три отмеченных пункта делают вариант ответа №1 неверным.
Есть здесь JetBrains?

namespace System::Customizer
{
    public class Foo { }
}


R# никаких синтаксических ошибок не показывает, однако не компилируется
Спасибо за наводку, создал кейс в трекере. Судя по всему, на названии пространств имен валидации нет вообще. Будем разбираться.
По поводу const vs readonly тоже можно побольше написать. Например, что будет, если скомпилировать сборку, в которой используется константа из другой сборки.
Везде можно побольше написать, я старался написать побольше там, где меньше правильных ответов.
Недавно натолкнулся на эту разницу при написании компилятора. Оказывается, даже если поле получается через Type.GetField(), с ним можно взаимодействовать командой ldfld только если у этого поля флаг IsLiteral == false. В противном случае необходимо разрешать значение на уровне компилятора и прошивать его значение константой — иначе вылезает MissingFieldException.

Если кому-нибудь интересно, могу написать небольшую на тему того, какие тонкости и подводные камни ждут желающих писать .NET-совместимые языки.
Да! Интересно — пишите!
Например, что будет, если скомпилировать сборку, в которой используется константа из другой сборки.
Отвечу за автора:
Константа попадает в кучу "#US" в метаданные сборки, которая ссылается на родительскую сборку.
При этом, данное поведение характерно не только для .NET, но и для C++. (Естественно, без метаданных).

Т.е. при изменении константы в родительском PE файле и без перекомпиляции дочернего PE файла константа останется прежней.
Константа попадает в кучу "#US" в метаданные сборки

Ой, фигню написал. Правильно будет:
Константа попадает в поток #US (Unicode Stream) находящейся в куче метаданных.
НЛО прилетело и опубликовало эту надпись здесь
Методы, помеченные как Conditional удобны тем, что не нужно писать #if — #endif раскоряку. В стандартных классах используется, например, в методах System.Diagnostics.Debug — WriteLine, Assert и т.п. Напоминает partial методы, которые можны вызывать, даже если они не имеют тела.
используем в фирме более привычные С-шному программисту #if
Правильно делаете. Т.к. один из первых хаков Ultrapico Espresso (не знаю как сейчас) заключался в том, что в коде был оставлен тестовый метод с атрибутом Conditional, который запускал программу без проверки ключа лицензии.
Т.е. для кряка достаточно было загрузить сборку в память и через рефлексию вызвать тестовый метод.
А откуда вопросы?

В It Academy кажется один в один
Да, эти вопросы выборочно взяты из открытого тестирования ВМК МГУ по программе Microsoft It Academy для сертификации респондентов.
Ваш вариант ответа на вопрос 11 очень спорный. Мне все таки кажется верными будут 2-й и 4-й варианты ответа. Изначально генерируется предупреждение. В студии можно поставить warning as error, но в этом случае про любое предупреждение можно говорить — «оно будет либо предупреждение либо ошибка в зависимости от настроек студии». Тут неточность в формулировке и скорее из за этого большинство ответили на вопрос именно так (гадая что вы имели ввиду).
Как по мне, там три варианта ответа подходит — 1, 2 и 4, в зависимости от ситуации.
Например, если я помечу свойство атрибутом и где нибудь буду использовать это свойство — я получу предупреждение.
А если я, как второй параметр этого атрибута, поставлю true и буду использовать это свойство — то получу ошибку компиляции.
А если я не буду использовать свойство с этим атрибутом вообще — то всё будет хорошо и это никак не повлияет на компиляцию.
Интересно зачем это нужно. Я вот сделал много проектов с нуля на C# / .Net, и ответы на многие вопросы так никогда и не узнаю в своей жизни. И считаю, что это хорошо. Потому что голова свободна для полезной информации. А если мне что-то нужно, то всегда могу посмотреть в справке.
Немного критики:
1) Атрибут Conditional служит для указания компилятору компилировать или не компилировать метод, в зависимости от того установлено ли соответствующее значение #define.
Если Вы посмотрите IL код, то найдёте свой метод скомпилированным в коде, но вот все вызовы метода будут удалены.
Т.е. при написании такого кода:
[System.Diagnostics.Conditional("TEST")]
public void Test()
{
	MessageBox.Show("I want cookie");
}
ctor()
{
	this.Test();
	this.GetType().InvokeMember("Test", BindingFlags.InvokeMethod, null, this, null);
}

Метод Test() выполнится хотя-бы единожды.

2) Атрибутом Obsolete отмечается нерекомендуемая для использования сущность программы. Каждый случай использования сущности, отмеченной устаревшей, будет приводить к генерированию предупреждения или ошибки в зависимости от настроек этого атрибута.

Про настройки проекта в вопросе не упомянуто, значит, берём поведение по умолчанию. Указание атрибута:
[Obsolete]
На методе в соданном решении, без изменения свойств решения приведёт именно к предупрежению:
public ObsoleteAttribute()
{
	this._message = null;
	this._error = false;
}

Серьезно… Внес исправления в пост.
поломались картинки, а в них вопросы — самое важное в этой статье.
исправьте пожалуйста.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории