Pull to refresh

Comments 31

Вот пример «подвоха» который на мой взгляд «подвох»…
using System; using System.Xml; class Program { private static void Main() { Bar(XmlWriter => XmlWriter.Flush()); Bar(XmlReader => XmlReader.Flush()); } private static void Bar(Action<XmlWriter> x) { Console.WriteLine("W"); } private static void Bar(Action<XmlReader> x) { Console.WriteLine("R"); } }

UPD: мдя, форматирование слетело, извиняйте… за подробностями в 7.5.4.1 читать
Забавный пример на внимательность ;-). Выложил ваш пример на пастбин с нормальным форматом.
Да таких примеров можно напридумывать тысячи. Например еще пример из цикла «скомпилится или нет»…
ИМХО почти все примеры в топике напрямую следуют из первой главы любого «самоучителя по це решетка за 21 час»...
Я не знал как хабр воспримет задачи, поэтому из трёх десятков накиданных, выбирал не замудрёные, простые, чтобы было интересно всем. Но если в целом материал понравится, я готов написать ещё, более сложные
«Я думаю нет смысла удлинять пост и делать анализ задач» — как раз наоборот. Анализа каждой задачи (ответа на вопрос «почему именно такой результат») как раз и не хватает.
Я начал расписывать ответы, но когда увидел что перенося их в VS даже не нужно компилировать, статический анализатор сразу показывает что код содержит ошибки. Я подумал, что буду комментарии типа: спасибо капитан. А сейчас вижу, что нужно было расписать хотя бы последние 3 примера
Вы правда считаете, что прыгать вверх-вниз, чтобы проверить ответ — удобно?
UFO landed and left these words here
Я тоже недавно наткнулся на некоторые возможности C# и .Net про которые раньше вообще не слышал. Надеюсь, никто не будет против, если поделюсь одной из них =)

Eсть в солюшене есть три проекта:

ClassLibrary1:
namespace Foo {
	public static class Bar {
		public static void Do() {
			System.Console.WriteLine("ClassLibrary1");
		}
	}
}


ClassLibrary2:
namespace Foo {
	public static class Bar {
		public static void Do() {
			System.Console.WriteLine("ClassLibrary2");
		}
	}
}


И ещё консольное приложение, которое ссылается на оба проекта. Как в методе Main этого приложения вызвать оба метода без рефлексии?

Ответ
В проекте консольного приложения свойствах ссылок на другие проекты можно назначить алиасы ClassLibrary1 и ClassLibrary2. После этого такой код будет компилироваться:
extern alias ClassLibrary1;
extern alias ClassLibrary2;

public class Program {
	public static void Main() {
		ClassLibrary1.Foo.Bar.Do();
		ClassLibrary2.Foo.Bar.Do();
	}
}

А пример №8 всё же можно заставить компилироваться, лямбды поддерживают ref и out параметры.

Нужно объявить свой тип делегата:
public delegate void ActionWithRef(ref int value);

А потом объявить делегат, явно указав ref и тип параметра:
ActionWithRef action = (ref int value) => { i = i++; };
Очень интересно, но, как бы мягче выразиться, оторвано от реальной жизни (надеюсь).
А вот мне стала интересна эта задача и я хочу дать её разбор:
private void Do()
{
    int i = 0;
    i += Increment(ref i);

    Console.WriteLine(i);
}

private int Increment(ref int i)
{
    return i++;
}

Я после беглого просмотра предположил что будет 2. Но нет, постфиксная форма инкремент приведёт к тому что мы уйдём из метода до того как изменим переменную, в результате чего ref не сыграет ни какой роли, из метода вернётся тоже что в него и было отправлено.
Но нет, постфиксная форма инкремент приведёт к тому что мы уйдём из метода до того как изменим переменную
Почему тогда, если мы перепишем вот так:
private static int Increment(ref int i)
{
    int r = i++;
    return r;
}
, то получим тот же результат?

А если напишем
int i = 0;
int j = Increment(ref i);
i += j;
, то уже получим единицу?
Потому что сначала переменной r присвоится 0, а потом i увеличится на единицу. Следовательно, когда метод отработает, он вернёт результат 0, и уже неважно чему равно i, мы новой переменной j присваиваем результат, то бишь 0.
Я понимаю, что код i += Increment(ref i); по сути превращается в i += 0;. Но ведь внутри Increment мы уже увеличили i. Получается, что к i, равному 1, мы добавляем 0. Должно получиться 1.
Это операция произойдёт если мы останемся в методе, но мы из него выходим следовательно увлечение не произойдёт.
Увеличение произойдет. Попробуйте вариант с j.
Если посмотреть дизассемблером в MSIL код, то можно увидеть, что перед вызовом метода Increment значение i сохраняется в стек, и уже именно с этим значением и суммируется.
i += Increment(ref i); превращается в i = i + Increment(ref i); который, в свою очередь, вычисляется слева направо. Поэтому компьютер успевает «прочитать» i до того, как вызовет Increment. Но в любом случае, лучше так не делать.
В чем соль поста? Кому он будет полезен, профессионалом которые и так скорей всего знают ответы на данные вопросы(т.к. вопросы не очень сложны), новичкам он полностью бесполезен?
С такой же легкостью можно написать пример про IEnumerable и IQueryable и не чего не объясняя дать ответ и сказать мол у вас же есть VS разбирайтесь господа почему так.
Для проверки на знание языка. Например, 8 задача скорее звучит как «можно ли в лямбде пользоваться ref-модификатором и если да, то какие особенности выполнения это влечёт?» А 10 вообще одна из самых часто встречаемых ошибок при работе с Linq, «Multiple enumeration». Как раз задачи очень хорошие, т. к. выясняют не знание каких-то малоизвестных библиотек, а логику, самые базовые знания C# и внимательность.
Я не против задач, я против таких постов. Какую смысловую нагрузку несет данный пост?
IMHO по-моему нужны расписанные ответы с объяснением, а не ссылаться мол сами разбирайтесь.
IMHO по-моему нужны расписанные ответы с объяснением, а не ссылаться мол сами разбирайтесь.

А может быть, если человек разберётся сам, то это будет полезнее, он немного продвинется от «что и как» к «почему и зачем сделано именно так»?
Ну к сожалению бешенство людей ленивы. Или вот я решил разобраться с задачей(одной из выше описанных). Первое что приходит в голову, это гуглить. Скорей всего первые результаты поиска будут ссылаться на хабр. И в чем профит, если я не могу найти точку входа(точнее найденный результат не чего первоначального не объясняет, а задаёт только вопрос)?
Именно поэтому. Если в сети где-то будет разжеванный ответ, то никакой пользы для ленивого человека от него не будет — он получит расшифровку одного факта из тысячи, очередную рыбу вместо удочки. И возникает вопрос — а нужен ли ему был этот ответ сам по себе? Конечно, можно представить себе ситуацию, когда он придумал сложную архитектуру, завязанную на использование ref-аргументов в лямбда-выражении, и только при попытке воплотить её обнаружил, что она не работает.
Хотя по последней задаче я не отказался бы от комментария вроде «Where — ленивая функция». В описании, которое предлагает VS, я этого не увидел (наверное, считается, что все это и так знают). Теперь придётся искать, где подобные функции перечислены, чтобы не воспользоваться ими в ситуации, когда необходимо создавать новый объект, а не просто итератор.
Соглашусь с вами вы меня переубедили :) тот кому это нужно и интересно найдет :), а ленивый — ССЗБ
«10 Подсчитайте, чему равно linqCounter?»
ответ — будет равно 7, а 8 выведется в консоль
Sign up to leave a comment.

Articles