Comments 37
Спрячьте пожалуйста статью под кат.
0
Спасибо за статью. Некоторых описанных вещей не знал.
+3
UFO just landed and posted this here
Результатом работы, как всегда в этой статье, будет вывод числа «20», а никак не «10».
…
и результатом работы следующий программы будет 5, а не 10.
:)
+2
UFO just landed and posted this here
Статья полезная, приятно, что не пришлось ничего гуглить, а только освежить знания.
P.S. Хм, в последнем примере IsValid по семантике больше похоже на IsInvalid.
P.S. Хм, в последнем примере IsValid по семантике больше похоже на IsInvalid.
+1
> Кроме выше описанных, есть еще одно чудо-слово __arglist, которое позволяет сделать функцию с переменным числом параметров, да еще и любого типа.
> Странным является то, что нельзя из коробки организовать проход по элементам с помощью foreach, да и напрямую к элементу из списка не обратиться. Так что до С++ или JavaScript c его arguments не дотягивает.:)
Вообще-то и в этом плане дотягивает и ещё мощнее даже — используйте params ( url=https://msdn.microsoft.com/en-us/library/w5zay9db.aspx ). Cтрогая типизация и можно совмещать в одной сигнатуре метода постоянное и переменное число аргументов. Например, такой метод:
void Test(int a, params int[] extraArgs) { }
// пример вызова
Test(1, «extraArg», «extraArg2», «extraArgN»);
> Странным является то, что нельзя из коробки организовать проход по элементам с помощью foreach, да и напрямую к элементу из списка не обратиться. Так что до С++ или JavaScript c его arguments не дотягивает.:)
Вообще-то и в этом плане дотягивает и ещё мощнее даже — используйте params ( url=https://msdn.microsoft.com/en-us/library/w5zay9db.aspx ). Cтрогая типизация и можно совмещать в одной сигнатуре метода постоянное и переменное число аргументов. Например, такой метод:
void Test(int a, params int[] extraArgs) { }
// пример вызова
Test(1, «extraArg», «extraArg2», «extraArgN»);
+1
params — всё же типизирован, в отличии __arglist. Хотя никто не мешает сделать всё тот же пресловутый dynamic.
static void Main(string[] args)
{
Foo(10, "asd");
}
public static void Foo(params dynamic[] list)
{
foreach (var item in list)
Console.WriteLine(item);
}
0
Вот в чем смысл всюду dynamic совать? Конкретно в этом примере достаточно object.
+4
Немаловажное отличие __arglist от params — в него можно передавать unsafe указатели, а затем доставать их через __refvalue. Указатель нельзя скастовать ни к object ни к dynamic.
+5
Я не придираюсь, но по поводу пары вещей:
А еще можно написать так:
class A
{
public List Numbers => new List();
}
И в последнем случае вас будет ждать неприятный сюрприз. На самом деле, в последнем примере вы создали вот такое вот свойство:
class A
{
public List Numbers { get { return new List(); } }
}
А чего еще можно ожидать создав метод который возвращает новый список? Здесь нет никакого сюрприза.
Аналогично кРезультатом работы будет вывод числа «20», а никак не «10»., вы же сами написали что это мутатор.
Про символ @ в документации к языку все сказано, введен чтобы можно было использовать ключевые слова, также ожидаемое поведение.
Т.е. про большую часть статьи сказать WTF C# нельзя, поведение соответствует ожидаемому и документации.
0
По поводу @ и value.
VS подсвечивает, value в set-ре как ключевое слово, и тем самым создавая определенную неоднозначность в этом моменте.
В приведенном примере, мы, казалось бы, изменяем одно и тоже поле класса А:
Но это не так. Данное поведение происходит из-за не соответствия @value в get и @value в set. @value в get будет являться ничем иным, кроме как, полем класса A. А @value в set на самом деле — это параметр функции set. Таким образом мы просто пишем value само в себя и никак не затрагиваем поле value в классе А.
Именно эту суть я и хотел донести. А кстати, в VS2012 и ниже подсветка переменных осуществляется некорректно.
А, касаемо
В предыдущем стандарте языка такого не было [Ну или как минимум VS 2013 выдает ошибку синтаксиса]. Вот и хотелось поведать о таких вот способах и предостеречь от ошибок.:)
VS подсвечивает, value в set-ре как ключевое слово, и тем самым создавая определенную неоднозначность в этом моменте.
В приведенном примере, мы, казалось бы, изменяем одно и тоже поле класса А:
get { return @value; }
set { @value = value; }
Но это не так. Данное поведение происходит из-за не соответствия @value в get и @value в set. @value в get будет являться ничем иным, кроме как, полем класса A. А @value в set на самом деле — это параметр функции set. Таким образом мы просто пишем value само в себя и никак не затрагиваем поле value в классе А.
Именно эту суть я и хотел донести. А кстати, в VS2012 и ниже подсветка переменных осуществляется некорректно.
А, касаемо
public List Numbers => new List();
В предыдущем стандарте языка такого не было [Ну или как минимум VS 2013 выдает ошибку синтаксиса]. Вот и хотелось поведать о таких вот способах и предостеречь от ошибок.:)
+1
На самом деле при помощи __makeref() и __refvalue() реализуется всякий брутальный unsafe в стиле «а теперь берем этот указатель на массив байтов и ловким движением руки превращаем его в указатель на структуру».
Я только что побенчил — функция «GenericPtrToStructure» получается примерно в 100 раз быстрее чем лучший ответ на StackOverflow: stackoverflow.com/questions/2871/reading-a-c-c-data-structure-in-c-sharp-from-a-byte-array
Я только что побенчил — функция «GenericPtrToStructure» получается примерно в 100 раз быстрее чем лучший ответ на StackOverflow: stackoverflow.com/questions/2871/reading-a-c-c-data-structure-in-c-sharp-from-a-byte-array
+1
Люто бешенно плюсую за статью! Некоторые моменты открыл для себя.
А по поводу замыканий и примера:
есть добавить пять копеек…
Действительно, цикл for захватывает замыкания и значение будет определятся на момент использования результата. «Фиксится» копированиев во временную переменную
Но вот тут:
доовольно интересная тема — до C# 5.0 была аналогичная ситуация, что и для for, а вот с выходом указанной версии на каждой итерации создается новая копия f (что-то типа «фикса»).
MS официально признала это изменение в языке версии 5.0 ломающим написанный ранее код, но в то же время были вынуждены пойти на этот шаг, так как по концепции foreach скоуп создаваемых переменных внутри foreach.
А по поводу замыканий и примера:
for (int i = 0; i < numbers.Length; i++)
result[i] = numbers.Where(index => index < i);
есть добавить пять копеек…
Действительно, цикл for захватывает замыкания и значение будет определятся на момент использования результата. «Фиксится» копированиев во временную переменную
var localIndex = i;
Но вот тут:
foreach(var f in fooList)
доовольно интересная тема — до C# 5.0 была аналогичная ситуация, что и для for, а вот с выходом указанной версии на каждой итерации создается новая копия f (что-то типа «фикса»).
MS официально признала это изменение в языке версии 5.0 ломающим написанный ранее код, но в то же время были вынуждены пойти на этот шаг, так как по концепции foreach скоуп создаваемых переменных внутри foreach.
+3
UFO just landed and posted this here
Многие упомянутые вещи с натяжкой можно назвать «подводными камнями». Больше похоже на намеренный выстрел себе в ногу.
+1
Хорошая статья — дает представление о возможных пунктах, которые стоит упомянуть в coding conditions…
+1
UFO just landed and posted this here
Хехе… public void Foo(__arglist) напрочь вышибает VS2015. Может в resharper проблема, но студия крашится через 2 секунды :).
0
Sign up to leave a comment.
Занимательный C#