Искренне желаю тебе однажды купить микроволновку, где одно нажатие выставляет 10 секунд х 900 Вт, два нажатия — включают гриль на два часа, три нажатия — 30 секунд х 900 Вт, четыре — 40, и так далее.
Здравствуйте, _FRED_, Вы писали:
_FR>Open you mind — вспомните, что для платформы .NET существует множество языков, ни один из которых не обязан поддерживать params.
Я бы посоветовал ровно это же в ответ: Если отбросить маркетоидную шелуху, для платформы .НЕТ существует ОДИН ПОЛНОЦЕННЫЙ ЯЗЫК — C#.
Здравствуйте, _FRED_, Вы писали:
_FR>Что лишний раз напоминает о том, что параметры следует проверять на null Чего ужасного-то "params" — это всего лишь атрибут для компилятора. Ничего удивительного.
Здравствуйте, Кодёнок, Вы писали:
Кё>Искренне желаю тебе однажды купить микроволновку, где одно нажатие выставляет 10 секунд х 900 Вт, два нажатия — включают гриль на два часа, три нажатия — 30 секунд х 900 Вт, четыре — 40, и так далее.
Нет, не купить, а получить в подарок от жены. На 25 лет свадьбы. Так, чтобы не отвертелся
ВВ>В твоем варианте я так не смогу. Т.е. хуже уже стало, а вот бенефиты сомнительны.
Для подобных случаев прекрасно сработает костыль: если params сущность передаётся в другую функцию в аргументе params, она незаметно развёртывается. Что тут сложного?
Я больше скажу: ДАЖЕ если бы это не было возможно, архитектурная стройность языка превыше микросекундных выйгрышей. Увы, но с текущим поведением C# напоминает студенческую лабораторку, где за 10 минут до сдачи "улучшили" скорость. "И эти люди учат меня не ковыряться в носу!" (ц)
Кё>class Problem
Кё>{
Кё> static void foo(params object[] ps)
Кё> {
Кё> System.Console.WriteLine("got {0} parameters for great good", ps.Length);
Кё> }
Кё> public static void Main()
Кё> {
Кё> foo(null, null, null, null);
Кё> foo(null, null, null);
Кё> foo(null, null);
Кё> foo(null); // HUH WHAT THE HELL
Кё> foo();
Кё> }
Кё>}
Что лишний раз напоминает о том, что параметры следует проверять на null Чего ужасного-то "params" — это всего лишь атрибут для компилятора. Ничего удивительного.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Кодёнок, Вы писали:
_FR>>Ответы специалистов, кстати, в первом же результате поиска Кё>Косяк дизайна языка я считаю. Надо было потребовать писать params, если программист хочет передать все параметры одним массивом:
Кё>object[] x = new object[] { "fred", "he", "is", "not", "null" };
Кё>foo(params x) // ps: x (5 параметров-строк)
Кё>foo(x) // ps: object[] { x } (один параметр-массив)
Ну а ИМХЕ больше кажется подходящим имеющийся вариант, любезно разобранный по косточкам здесь
.
Кё>Искренне желаю тебе однажды купить микроволновку, где одно нажатие выставляет 10 секунд х 900 Вт, два нажатия — включают гриль на два часа, три нажатия — 30 секунд х 900 Вт, четыре — 40, и так далее.
А попробовать объяснить, что в существующем варианте плохо и чем же предложенный вариант лучше не желаете?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
Кё>>Искренне желаю тебе однажды купить микроволновку, где одно нажатие выставляет 10 секунд х 900 Вт, два нажатия — включают гриль на два часа, три нажатия — 30 секунд х 900 Вт, четыре — 40, и так далее.
_FR>А попробовать объяснить, что в существующем варианте плохо и чем же предложенный вариант лучше не желаете?
Я не умею такие вещи объяснять. Что плохого в микроволновке из примера? Просто вижу что плохо, вот и все.
Здравствуйте, Кодёнок, Вы писали:
Кё>>>Искренне желаю тебе однажды купить микроволновку, где одно нажатие выставляет 10 секунд х 900 Вт, два нажатия — включают гриль на два часа, три нажатия — 30 секунд х 900 Вт, четыре — 40, и так далее. _FR>>А попробовать объяснить, что в существующем варианте плохо и чем же предложенный вариант лучше не желаете? Кё>Я не умею такие вещи объяснять. Что плохого в микроволновке из примера? Просто вижу что плохо, вот и все.
На а объяснить что общего у приведённой аналогии и обсуждаемого вопроса можно?
Мне, кстати, нужна микроволновка, у которой не сбрасываются часы при отключении электричества.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Кодёнок, Вы писали:
_FR>>На а объяснить что общего у приведённой аналогии и обсуждаемого вопроса можно?
Кё>Что общего между: Кё>foo() -> ноль слонят Кё>foo(x) -> попугай Кё>foo(x, x) -> два слоненка Кё>foo(x, x, x) -> три слоненка Кё>и Кё>одно нажатие -> один слоненок Кё>два нажатия -> попугай Кё>три нажатия -> три слоненка Кё>четыре нажатия -> четыре слоненка Кё>Это надо объяснять?
Конечно. Потому что далеко не каждый Кё>foo(x) -> попугай
а лишь при стечении некоторых обстоятельств.
using System.Diagnostics;
static class Program
{
static void Main() {
Test();
Test(0); // Никакой не "попугай", не разводите напраслину, учите матчасть
Test(0, 1);
Test(0, 1, 2, 3);
Test(null); // А вот тут очень ясно, что будет происходить
}
static void Test(params int[] values) {
if(values == null) {
Debug.Print("values == null");
} else {
Debug.Print("values.Length == {0}", values.Length);
}//if
}
}
А то, что в некоторых режимах кнопки выполняют не совсем те роли, которые выполняют в привычных условиях — обычное дело.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Мне, кстати, нужна микроволновка, у которой не сбрасываются часы при отключении электричества.
Offtop: А зачем часы в микроволновке? Нет часов — нет проблемы.
Здравствуйте, Spiceman, Вы писали:
_FR>>Мне, кстати, нужна микроволновка, у которой не сбрасываются часы при отключении электричества. S>Offtop: А зачем часы в микроволновке? Нет часов — нет проблемы.
У меня на кухне из часов только микроволновка Удобно — пока готовишь, голову не надо вертеть, что бы на часы посмотреть — над головой-то полки да шкафчики, туда часы не повесишь. А лепестричество вырубается днём в рабочие часы не редко
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Кодёнок, Вы писали:
_FR>>Конечно. Потому что далеко не каждый Кё>>>foo(x) -> попугай _FR>>а лишь при стечении некоторых обстоятельств.
Кё>Ну будет твоя микроволновка включать гриль вместо 20 сек не всегда, а только когда в комнате темно. Суть не меняется.
Ну почему сразу гриль-то? Вот в режиме настройки времени кнопка таймера устанавливает время. Мне это не мешает готовить пищу.
Help will always be given at Hogwarts to those who ask for it.
Вообще конечно баян, о котором даже в некоторых книгах написано. Например, насколько я помню, Рихтер писал что это сделано для большей эффективности — мол не надо создавать массив и потом его garbage-collect'ить. А то что передается null, а не пустой массив — ну тут тоже, насколько я помню, в методах, принимающих массивы или коллекции, аргумент равный null принято считать за пустую коллекцию, т.е. метод должен быть готов, что ему могут передать null (в общем-то практически любой метод должен это проверять) и трактовать такую ситуацию так же, как и передачу пустого массива/коллекции.
Здравствуйте, MozgC, Вы писали:
MC>Например, насколько я помню, Рихтер писал что это сделано для большей эффективности — мол не надо создавать массив и потом его garbage-collect'ить.
В CLR via C#? Я именно после той главы и написал этот пример. Слишком уж очевидный косяк.
Эффективность тут ни при чем, это чисто проблема парсера. foo(params null) не помешало бы этому, зато позволило бы избежать конфузов.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Конечно. Потому что далеко не каждый Кё>>>>foo(x) -> попугай _FR>>>а лишь при стечении некоторых обстоятельств.
Кё>>Ну будет твоя микроволновка включать гриль вместо 20 сек не всегда, а только когда в комнате темно. Суть не меняется. _FR>Ну почему сразу гриль-то? Вот в режиме настройки времени кнопка таймера устанавливает время. Мне это не мешает готовить пищу.
Внимание:
— один и тот же метод
— один и тот же параметр одного и того же типа (даже физически тот же самый объект)
— один и тот же синтаксис вызова
и при этом — разная семантика
Банальный копи-паст из обычного метода в дженерик присылает граблями по лбу.
Здравствуйте, Кодёнок, Вы писали:
Кё> foo(null, null); Кё> foo(null); // HUH WHAT THE HELL
Мне кажется, претензии вполне обоснованные. Если я написал params, меня не колышет, кто и что там передал — ps должен быть не null и содержать пусть даже пустой список — Я ЭТО ЗАПРОСИЛ ключевым словом.
А эта индусская оптимизация только вводит в диссонанс, коверкая интуитивную семантику языка.
Здравствуйте, matumba, Вы писали:
M>Мне кажется, претензии вполне обоснованные. Если я написал params, меня не колышет, кто и что там передал — ps должен быть не null и содержать пусть даже пустой список — Я ЭТО ЗАПРОСИЛ ключевым словом. M>А эта индусская оптимизация только вводит в диссонанс, коверкая интуитивную семантику языка.
int[] arr = new int[0, 1, 2];
foo(arr);//Что ожидаете в этом случае?int[] arr = null;
foo(arr);//А в этом случае?
Здравствуйте, matumba, Вы писали:
Кё>> foo(null, null); Кё>> foo(null); // HUH WHAT THE HELL
M>Мне кажется, претензии вполне обоснованные. Если я написал params, меня не колышет, кто и что там передал — ps должен быть не null и содержать пусть даже пустой список — Я ЭТО ЗАПРОСИЛ ключевым словом. M>А эта индусская оптимизация только вводит в диссонанс, коверкая интуитивную семантику языка.
Open you mind — вспомните, что для платформы .NET существует множество языков, ни один из которых не обязан поддерживать params. Как такие языки должны вызывать ваши методы? Кто и как обеспечит то, что вместо параметра-массива params не сможет придти null?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>int[] arr = new int[0, 1, 2]; ВВ>>foo(arr);//Что ожидаете в этом случае?
Кё>ожидаю ps : new object[] { new int[] {0,1,2} }
ВВ>>int[] arr = null; ВВ>>foo(arr);//А в этом случае?
Кё>ожидаю ps : new object[] { null }
Кё>Это довольно просто: params + N параметров при вызове = массив из N элементов на входе, нет?
Как уже писали, этот метод будет мертв для языков без поддержки params.
Здравствуйте, Кодёнок, Вы писали:
ВВ>>int[] arr = new int[0, 1, 2]; ВВ>>foo(arr);//Что ожидаете в этом случае? Кё>ожидаю ps : new object[] { new int[] {0,1,2} } ВВ>>int[] arr = null; ВВ>>foo(arr);//А в этом случае? Кё>ожидаю ps : new object[] { null } Кё>Это довольно просто: params + N параметров при вызове = массив из N элементов на входе, нет?
Мне вот было бы непросто. Поведение в первом случае мне не нравится совсем. Я если я пишу метод-враппер, который принимает params и передает их в другой метод с params? Что делать? Переливать из пустого в порожнее? Сейчас первый вариант работает так, как мне нужно, а второй проблемы не составляет.
Здравствуйте, samius, Вы писали:
S>Как уже писали, этот метод будет мертв для языков без поддержки params.
Еще раз пишу, что речь исключительно о синтаксисе вызова в языке c# и в самом методе и его декларации НИЧЕГО (т.е. ничего, это значит — ничего) не изменится. Языки без поддержки params это не затронет никоим образом.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Я если я пишу метод-враппер, который принимает params и передает их в другой метод с params? Что делать?
Тогда опля — пишем во враппере foo(params arr) вместо foo(arr) и имеем гарантию, что передали массив params, а не 1 параметр, независимо от контекста и типов.
Здравствуйте, Кодёнок, Вы писали:
ВВ>>Я если я пишу метод-враппер, который принимает params и передает их в другой метод с params? Что делать? Кё>Тогда опля — пишем во враппере foo(params arr) вместо foo(arr) и имеем гарантию, что передали массив params, а не 1 параметр, независимо от контекста и типов.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, samius, Вы писали:
S>>Как уже писали, этот метод будет мертв для языков без поддержки params.
Кё>Еще раз пишу, что речь исключительно о синтаксисе вызова в языке c# и в самом методе и его декларации НИЧЕГО (т.е. ничего, это значит — ничего) не изменится. Языки без поддержки params это не затронет никоим образом.
А кто будет переписывать уже существующий код на C#?
По-моему проблема вообще не в params, а в том что null нетипизирован.
foo((object)null);
работает как надо.
Здравствуйте, samius, Вы писали:
S>А кто будет переписывать уже существующий код на C#?
Введение breaking changes не есть нечто невероятное. Тем более рефлексия и верифицируемость кода позволяют автоматическими тулсами выдать на блюдечке все потенциально проблемные места, возможно даже исправить автоматом.
S>По-моему проблема вообще не в params, а в том что null нетипизирован.
Проблема вообще не в null, см. пример с делегатами, где его нет, а проблема есть. Я поспешил с названием топика, теперь часть ответов вообще не в тему.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, samius, Вы писали:
S>>А кто будет переписывать уже существующий код на C#?
Кё>Введение breaking changes не есть нечто невероятное. Тем более рефлексия и верифицируемость кода позволяют автоматическими тулсами выдать на блюдечке все потенциально проблемные места, возможно даже исправить автоматом.
А ради чего?
S>>По-моему проблема вообще не в params, а в том что null нетипизирован.
Кё>Проблема вообще не в null, см. пример с делегатами, где его нет, а проблема есть. Я поспешил с названием топика, теперь часть ответов вообще не в тему.
В примере с дженериком несколько неожиданно, но вполне логично. Было бы странно, если бы он работал как-то по-другому.
Здравствуйте, Кодёнок, Вы писали:
ВВ>>В твоем варианте я так не смогу. Т.е. хуже уже стало, а вот бенефиты сомнительны. Кё>Сможешь, ты видимо не понял идею. В моем варианте Bar(params args) отфорвардит готовый массив, Bar(args) создаст новый из 1 элемента.
Не понял. Давай с примерами кода. Мне в метод Foo(params) передали несколько параметров вида Foo(x, y, z). Я хочу эти параметры передать в метод Bar(params). Что я буду делать? Сейчас я могу просто передать массив args, ибо params есть тонкий сахар над массивом.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Не понял. Давай с примерами кода. Мне в метод Foo(params) передали несколько параметров вида Foo(x, y, z). Я хочу эти параметры передать в метод Bar(params). Что я буду делать?
как будет <=> как было
Bar(params args) <=> Bar(x, y, z); Bar(args)
Bar(args) <=> Bar( (object)args )
ВВ>int[] arr = new int[0, 1, 2];
ВВ>foo(arr);//Что ожидаете в этом случае?
Банально же, ps[0] = ссылка на массив трёх целых.
ВВ>int[] arr = null;
ВВ>foo(arr);//А в этом случае?
ВВ>
Здравствуйте, matumba, Вы писали:
M>Здравствуйте, _FRED_, Вы писали:
_FR>>Open you mind — вспомните, что для платформы .NET существует множество языков, ни один из которых не обязан поддерживать params.
M>Я бы посоветовал ровно это же в ответ: Если отбросить маркетоидную шелуху, для платформы .НЕТ существует ОДИН ПОЛНОЦЕННЫЙ ЯЗЫК — C#.
Один из неполноценных языков (хнык ), кстати, ведёт себя так же как C#:
type Foo =
static member Bar([<System.ParamArray>] ps : obj array) =
printfn "got %d parameters for great good" ps.Length
Foo.Bar(null, null, null, null)
Foo.Bar(null, null, null)
Foo.Bar(null, null)
Foo.Bar(null) (* аналогично *)
Foo.Bar()
Это ещё что... Об этом везде написано. Я другой пример покажу:
using System;
using System.Collections.Generic;
class Problem
{
static void Main()
{
var x = new[] { new List<string>(), new List<string>() };
Bar1(x);
Bar2(x);
}
static void Bar1<T>(T[] x) where T : IList<string>
{
Foo(x);
}
static void Bar2<T>(T[] x) where T : List<string>
{
Foo(x);
}
static void Foo(params object[] x)
{
Console.WriteLine(x.Length);
}
}
Здравствуйте, nikov, Вы писали:
N>Я другой пример покажу:
Владимир, а не могли бы Вы разъяснить логику компилятора в данном случае? У меня взорвало мозг...
У F# в данной ситуации всё ок:
open System
open System.Collections.Generic
type Problem =
static member Bar1(x: #IList<string>[]) = Problem.Foo(x)
static member Bar2(x: #List<string>[]) = Problem.Foo(x)
static member Foo([<ParamArray>] x: obj[]) = printfn "%d" x.Length
let xs : List<string>[] = [| |]
Problem.Bar1(xs) // 1
Problem.Bar2(xs) // 1