Comments 31
В чем подвохи-то?
Вот пример «подвоха» который на мой взгляд «подвох»…
UPD: мдя, форматирование слетело, извиняйте… за подробностями в 7.5.4.1 читать
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 час»...
ИМХО почти все примеры в топике напрямую следуют из первой главы любого «самоучителя по це решетка за 21 час»...
Выложил пример туда где его можно запустить http://dotnetfiddle.net/VBdP5k
Я не знал как хабр воспримет задачи, поэтому из трёх десятков накиданных, выбирал не замудрёные, простые, чтобы было интересно всем. Но если в целом материал понравится, я готов написать ещё, более сложные
«Я думаю нет смысла удлинять пост и делать анализ задач» — как раз наоборот. Анализа каждой задачи (ответа на вопрос «почему именно такой результат») как раз и не хватает.
Вы правда считаете, что прыгать вверх-вниз, чтобы проверить ответ — удобно?
Я тоже недавно наткнулся на некоторые возможности C# и .Net про которые раньше вообще не слышал. Надеюсь, никто не будет против, если поделюсь одной из них =)
Eсть в солюшене есть три проекта:
ClassLibrary1:
ClassLibrary2:
И ещё консольное приложение, которое ссылается на оба проекта. Как в методе Main этого приложения вызвать оба метода без рефлексии?
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 параметры.
Нужно объявить свой тип делегата:
А потом объявить делегат, явно указав ref и тип параметра:
Нужно объявить свой тип делегата:
public delegate void ActionWithRef(ref int value);
А потом объявить делегат, явно указав ref и тип параметра:
ActionWithRef action = (ref int value) => { i = i++; };
Очень интересно, но, как бы мягче выразиться, оторвано от реальной жизни (надеюсь).
А вот мне стала интересна эта задача и я хочу дать её разбор:
Я после беглого просмотра предположил что будет 2. Но нет, постфиксная форма инкремент приведёт к тому что мы уйдём из метода до того как изменим переменную, в результате чего ref не сыграет ни какой роли, из метода вернётся тоже что в него и было отправлено.
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.Это операция произойдёт если мы останемся в методе, но мы из него выходим следовательно увлечение не произойдёт.
Если посмотреть дизассемблером в MSIL код, то можно увидеть, что перед вызовом метода Increment значение i сохраняется в стек, и уже именно с этим значением и суммируется.
i += Increment(ref i);
превращается в i = i + Increment(ref i);
который, в свою очередь, вычисляется слева направо. Поэтому компьютер успевает «прочитать» i
до того, как вызовет Increment
. Но в любом случае, лучше так не делать.В чем соль поста? Кому он будет полезен, профессионалом которые и так скорей всего знают ответы на данные вопросы(т.к. вопросы не очень сложны), новичкам он полностью бесполезен?
С такой же легкостью можно написать пример про IEnumerable и IQueryable и не чего не объясняя дать ответ и сказать мол у вас же есть VS разбирайтесь господа почему так.
С такой же легкостью можно написать пример про IEnumerable и IQueryable и не чего не объясняя дать ответ и сказать мол у вас же есть VS разбирайтесь господа почему так.
Для проверки на знание языка. Например, 8 задача скорее звучит как «можно ли в лямбде пользоваться ref-модификатором и если да, то какие особенности выполнения это влечёт?» А 10 вообще одна из самых часто встречаемых ошибок при работе с Linq, «Multiple enumeration». Как раз задачи очень хорошие, т. к. выясняют не знание каких-то малоизвестных библиотек, а логику, самые базовые знания C# и внимательность.
Я не против задач, я против таких постов. Какую смысловую нагрузку несет данный пост?
IMHO по-моему нужны расписанные ответы с объяснением, а не ссылаться мол сами разбирайтесь.
IMHO по-моему нужны расписанные ответы с объяснением, а не ссылаться мол сами разбирайтесь.
IMHO по-моему нужны расписанные ответы с объяснением, а не ссылаться мол сами разбирайтесь.
А может быть, если человек разберётся сам, то это будет полезнее, он немного продвинется от «что и как» к «почему и зачем сделано именно так»?
Ну к сожалению бешенство людей ленивы. Или вот я решил разобраться с задачей(одной из выше описанных). Первое что приходит в голову, это гуглить. Скорей всего первые результаты поиска будут ссылаться на хабр. И в чем профит, если я не могу найти точку входа(точнее найденный результат не чего первоначального не объясняет, а задаёт только вопрос)?
Именно поэтому. Если в сети где-то будет разжеванный ответ, то никакой пользы для ленивого человека от него не будет — он получит расшифровку одного факта из тысячи, очередную рыбу вместо удочки. И возникает вопрос — а нужен ли ему был этот ответ сам по себе? Конечно, можно представить себе ситуацию, когда он придумал сложную архитектуру, завязанную на использование ref-аргументов в лямбда-выражении, и только при попытке воплотить её обнаружил, что она не работает.
Хотя по последней задаче я не отказался бы от комментария вроде «Where — ленивая функция». В описании, которое предлагает VS, я этого не увидел (наверное, считается, что все это и так знают). Теперь придётся искать, где подобные функции перечислены, чтобы не воспользоваться ими в ситуации, когда необходимо создавать новый объект, а не просто итератор.
Хотя по последней задаче я не отказался бы от комментария вроде «Where — ленивая функция». В описании, которое предлагает VS, я этого не увидел (наверное, считается, что все это и так знают). Теперь придётся искать, где подобные функции перечислены, чтобы не воспользоваться ими в ситуации, когда необходимо создавать новый объект, а не просто итератор.
«10 Подсчитайте, чему равно linqCounter?»
ответ — будет равно 7, а 8 выведется в консоль
ответ — будет равно 7, а 8 выведется в консоль
Sign up to leave a comment.
10 простых задач на c# с подвохом