Re[3]: Assertions
От: Sinix  
Дата: 31.03.16 16:11
Оценка: 6 (1) :)
Здравствуйте, rameel, Вы писали:

R>Я смотрел на них как на готовый набор предусловий для наиболее частых вариантов использования, которые заменяют всякие if (condition) throw в начале методов и конструкторов. Просто не нравится, когда проверки частых предусловий не консистентны. Вот взять тот же Split:


Ну а кто вам виноват, что используете недоделанную вещь?
Если серьёзно — мой косяк, не ожидал, что интерес будет. Рекомендации в процессе, за ними будут дополнения в самом Code Выше был пост с ответом AndrewVK, есть предложения/возражения — велкам!
Re[2]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 19:55
Оценка: 2 (1) +1
Здравствуйте, Sinix, Вы писали:

S>Вот тут надо подумать. Нам точно нужно запихивать специфичные ассерты именно в Code?


Диапазоны я бы не назвал специфичными. Оно нечастно бывает нужно, факт, но все таки оно весьма универсально. В ту же копилку проверки чисел на >0 и енумов на существование значения. Разносить их по разным классам не вижу смысла, Code сейчас явно не перегружен.
Вот если тип аргумента за пределами System, то надо в отдельный класс.

S>ассерты для IO -

S>
S>IOCode.FileExists("myFile.txt", "...")
S>и
S>DebugIOCode.StreamHasContent(values, v => v > 0);
S>


IO однозначно в отдельный класс и даже отдельный неймспейс.

S>1. NotNullNorWhiteSpace — нужен реальный юз-кейз. Я ещё не видел ни одного метода, в котором использовался бы такой ассерт.


Да вроде все очевидно, не? Мне такое регулярно попадается.

S>Вот NotNullNorEmpty для строк/enumerable/массивов можно добавить.

S>2. NotNullNorContainsNull — да, но это уже к продвинутым сценариям, хорошо бы в EnumerableCode запихнуть.

Тут спорно. Для enumerable лишняя итерация для проверки на empty — не айс. В 99% случаев лучше проверить в ходе основного энумерирования.
Можно в дебаг, наверное, воткнуть.

S>пойдёт. StateInRange не добавлять, если реального сценария нет.


Ну, если уж озабочиваться проверками инвариантов, то сценарий вполне реален.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 21:06
Оценка: 1 (1) +1
Здравствуйте, Sinix, Вы писали:

S>А можно пример?

S>А то я не могу сообразить, где допустима любая непустая строка, если она не из пробелов.

Всевозможные id'шники, пути, имена.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[7]: аллокации для params object[]
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.04.16 18:22
Оценка: :))
Здравствуйте, Sinix, Вы писали:

S>Эта штука не один раз нужна, навскидку методов 5 похожих точно найдётся.


Ага, в GetValueOrDefault например. После последних правок там 18 перегрузок. 18, Карл!
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re: аллокации для params object[]
От: Jack128  
Дата: 25.04.16 10:14
Оценка: 44 (1)
Здравствуйте, rameel, Вы писали:

Возможно имеет ли смысл добавлять перегрузку:
AssertArgument(
            bool condition,
            [NotNull, InvokerParameterName] string argName,
            [NotNull] string messageFormat,
            [CanBeNull] object arg)

чтоб убрать лишнее выделение памяти под массив.
Re[2]: Assertions
От: Lexey Россия  
Дата: 25.04.16 21:44
Оценка: 24 (1)
Здравствуйте, Sinix, Вы писали:

S>1. NotNullNorWhiteSpace — нужен реальный юз-кейз. Я ещё не видел ни одного метода, в котором использовался бы такой ассерт. Без реальных сценариев я код не добавляю, т.к. неизбежно получается сфероконь на выброс. Исключений не видел.


Приходит тебе какой-нибудь url, path или строковый id на вход, который хочется по-быстрому провалидировать, не заморачиваясь полноценной проверкой. Вот тут оно и пригодится, но скорее нужно NotNullNorEmptyNorWhiteSpace.
"Будь достоин победы" (c) 8th Wizard's rule.
Отредактировано 26.04.2016 17:02 Lexey . Предыдущая версия .
Re: Assertions
От: Sinix  
Дата: 02.04.16 17:21
Оценка: 12 (1)
Здравствуйте, rameel, Вы писали:

R>Предлагаю добавить в Code/DebugCode следующие методы для единообразия. Всех кейсов наверняка это не покроет, но частое закроет.


Забирай.

Code.InRange, ValidIndex, ValidIndexPair, ValidIndexAndCount, NotNullNorWhiteSpace
Дебаг-ассерты для всех сгенерены, примеры в тестах.

Перегрузки ValidIndex проверяют index >= 0, 0 <= index < length соответственно

ValidIndexPair: 0 <= from <= to < length

ValidIndexAndCount:
0 <= startIndex < length
+
0 <= count <= length-startIndex;
обычно используется в аналогах Substring/CopyTo etc

Для бросания исключений в switch по аргументу добавлен CodeExceptions.UnexpectedArgumentValue


Не сделаны: ассерты для массивов/коллекций/enumerable. Это в отдельное обсуждение плиз.

Доки в процессе, не всё сразу
Assertions
От: rameel https://github.com/rsdn/CodeJam
Дата: 30.03.16 16:11
Оценка: +1
Предлагаю добавить в Code/DebugCode следующие методы для единообразия. Всех кейсов наверняка это не покроет, но частое закроет.

NotNullNorWhiteSpace
NotNullNorContainsNull
ValidateRange // или Range|AssertRange? для ArgumentOutOfRangeException
ValidateIndexRange // или IndexRange|AssertIndexRange для для IndexOutOfRangeException


Остальное вроде все уже есть.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 16:16
Оценка: +1
Здравствуйте, rameel, Вы писали:

R>ValidateRange // или Range|AssertRange? для ArgumentOutOfRangeException

R>ValidateIndexRange // или IndexRange|AssertIndexRange для для IndexOutOfRangeException

С именами не консистентно. Лучше, наверное, RangeValid. Это ж assertion, т.е. утверждение, а не действие.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: Assertions
От: rameel https://github.com/rsdn/CodeJam
Дата: 31.03.16 16:03
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Вот тут надо подумать. Нам точно нужно запихивать специфичные ассерты именно в Code?


S>Дело в том, что Code.* задуман как расширяемая система.


Я смотрел на них как на готовый набор предусловий для наиболее частых вариантов использования, которые заменяют всякие if (condition) throw в начале методов и конструкторов. Просто не нравится, когда проверки частых предусловий не консистентны. Вот взять тот же Split:
public static IEnumerable<T[]> Split<T>([NotNull] this IEnumerable<T> source, int size)
{
    Code.NotNull(source, nameof(source));

    // Вот здесь хотелось бы не if & throw, а что-то типа такого как пример:
    // Code.RangeValid(size > 0, nameof(size))
    // с выбросом нужного исключения.
    if (size <= 0)
        throw new ArgumentOutOfRangeException(nameof(size));

    return SplitImpl(source, size);
}
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[9]: аллокации для params object[]
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.04.16 21:44
Оценка: +1
Здравствуйте, Jack128, Вы писали:

J>Смысл в том, что иногда у нас есть на например словарь Dictionary<int, List<MyClass>>, а в качестве дефолотового значения мы хотим задать IReadOnlyList<MyClass>


Как то уж слишком кучеряво и неочевидно.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: Assertions
От: rameel https://github.com/rsdn/CodeJam
Дата: 30.03.16 16:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>С именами не консистентно.


Эт точно

AVK>Лучше, наверное, RangeValid. Это ж assertion, т.е. утверждение, а не действие.




Будет RangeValid & IndexRangeValid так?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[3]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 16:37
Оценка:
Здравствуйте, rameel, Вы писали:

R>Будет RangeValid & IndexRangeValid так?


Как вариант. Главное чтобы звучало как утверждение.
И я бы еще переменовал AssertXxx. Например можно в соответствии со стандартным Contract — Requires, Invariant, Exists, Ensures, ForAll.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re: Assertions
От: Sinix  
Дата: 30.03.16 19:07
Оценка:
Здравствуйте, rameel, Вы писали:

R>Предлагаю добавить в Code/DebugCode следующие методы для единообразия. Всех кейсов наверняка это не покроет, но частое закроет.


R>
R>NotNullNorWhiteSpace
R>NotNullNorContainsNull
R>ValidateRange // или Range|AssertRange? для ArgumentOutOfRangeException
R>ValidateIndexRange // или IndexRange|AssertIndexRange для для IndexOutOfRangeException
R>


R>Остальное вроде все уже есть.


Вот тут надо подумать. Нам точно нужно запихивать специфичные ассерты именно в Code?

Дело в том, что Code.* задуман как расширяемая система. Не в смысле плагины и прочая мутотень, а в том смысле, что соблюдая набор простых рекомендаций очень легко добавлять новые наборы ассертов, не нарушая общей картины. Если от этих правил отклоняться, то получится явакошмар из NUnit — десяток перегрузок, из которых половина неудобна, а вторая нафиг не нужна.


Ну, т.е. ассерты для enumerable выглядят как
EnumerableCode.NotEmptyAndNoNulls(values, "...")
и
DebugEnumerableCode.AssertAll(values, v => v > 0); // только InvalidOperation, т.к. тут проблема с состоянием кода, а не с неверно переданными аргументами


ассерты для IO —
IOCode.FileExists("myFile.txt", "...")
и
DebugIOCode.StreamHasContent(values, v => v > 0);


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

1. NotNullNorWhiteSpace — нужен реальный юз-кейз. Я ещё не видел ни одного метода, в котором использовался бы такой ассерт. Без реальных сценариев я код не добавляю, т.к. неизбежно получается сфероконь на выброс. Исключений не видел.
Вот NotNullNorEmpty для строк/enumerable/массивов можно добавить.

2. NotNullNorContainsNull — да, но это уже к продвинутым сценариям, хорошо бы в EnumerableCode запихнуть.

3. ValidateRange — идём от сценария использования, пара:
Code.ArgumentInRange(insertIndex, nameof(insertIndex), 0, Count);

Code.StateInRange(position, nameof(position), -1, Length);


пойдёт. StateInRange не добавлять, если реального сценария нет.

4. ValidateIndexRange
Code.ValidIndex(index, nameof(index));
Code.ValidIndex(index, nameof(index), Count);
Re[4]: Assertions
От: Sinix  
Дата: 30.03.16 19:31
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Как вариант. Главное чтобы звучало как утверждение.

AVK>И я бы еще переменовал AssertXxx. Например можно в соответствии со стандартным Contract — Requires, Invariant, Exists, Ensures, ForAll.

Я с этого начинал. Не работает, если применять в промышленных масштабах. Можешь поверить, я это уже лет десять делаю
Точнее, так: Requires, Invariant, Exists, Ensures, ForAll можно сделать отдельной группой ассертов, не трогая существующие, но они будут малополезны.


Проблема с ассертами в том, что
1. Должны быть чёткие рекомендации, как оформлять ассерты. Без них получается яваад, когда половину кода нельзя использовать, а вторую половину — не нужно использовать.
Если придерживаться — то у пользователя новые ассерты не вызывают никаких вопросов, он даже про то, что есть какие-то правила оформления и не задумывается.
Рекомендации есть, оформлю.

2. Ассерты используются не в единице мест, а сотнями / тысячами. В больших проектах — легко за десятки тысяч. Соответственно, любой способ использовать неправильно будет использован неправильно, а любой косяк по перфомансу обязательно выстрелит.

В чём проблема с "переменовал AssertXxx":

Все ассерты делятся на
1. Ассерты, покрывающие готовые сценарии. Называются по имени проверяемого сценария (внезапно, ага )
Например, группа ассертов для валидации аргуметров. Обычно бросают ArgumentException/наследников.
Или группа ассертов для валидации состояния. Бросают InvalidOperationException, ObjectDisposed, FileNotExists etc

2. Базовые ассерты для каждой группы. Имя — Assert+Имя группы
Используются, когда в группе нет подходящих. Соответственно, AssertArgument и AssertState.

К базовым обязательно добавляется AssertBusiness для исключений биз-логики, дальше — в зависимости от задач.

Если базовые назвать как-то иначе, то все новые ассерты выбиваются из системы и начинается кто в лес, кто по дрова.
Re[5]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 19:48
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Я с этого начинал. Не работает, если применять в промышленных масштабах. Можешь поверить, я это уже лет десять делаю


Что именно не работает?

S>Точнее, так: Requires, Invariant, Exists, Ensures, ForAll можно сделать отдельной группой ассертов, не трогая существующие, но они будут малополезны.


Я не предлагаю копировать оттуда методы, я предлагаю переименовать AssertArg в ArgRequires.

S>1. Должны быть чёткие рекомендации, как оформлять ассерты. Без них получается яваад, когда половину кода нельзя использовать, а вторую половину — не нужно использовать.


Это к вопросу о Плагин к Решарперу/Розлину
Автор: AndrewVK
Дата: 29.03.16
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[6]: Assertions
От: Sinix  
Дата: 30.03.16 20:07
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Что именно не работает?

Ассерты называются как каждый автор захочет и получается примерно то, что сейчас творится с ассертами в Nunit: часть obsolete, часть дублирует существующие и без справки в этом болоте не разберёшься


S>>Точнее, так: Requires, Invariant, Exists, Ensures, ForAll можно сделать отдельной группой ассертов, не трогая существующие, но они будут малополезны.

AVK>Я не предлагаю копировать оттуда методы, я предлагаю переименовать AssertArg в ArgRequires.
А есть доводы за? Кроме довода "так сделано в code contracts", который не подходит, т.к. у контрактов немножко другая философия. Одно "нарушение контракта должно убивать процесс" чего стоит.


Против — вот прямо сходу есть два довода.

Во-первых, название метода перестаёт отвечать на вопрос: "какую проблему решает этот метод?"

Во-вторых, нарушается принцип наименьшего удивления.
Сравни сам:
Code.AssertArgument(arg > 0 && arg < 10, nameof(arg), "Some message1");

Code.AssertState(IsInitialized, "Some message2"); // InvalidOperationException

Code.AssertBusiness(CheckSomePolicy(), "Some message3");  // BusinessException

Code.AssertWeb(timeout.TotalSeconds < 15, "Some message4"); // WebException


Для первого сделаем ArgRequires, остальные как обзывать?
AssertState, к примеру, ни разу не Invariant.



S>>1. Должны быть чёткие рекомендации, как оформлять ассерты. Без них получается яваад, когда половину кода нельзя использовать, а вторую половину — не нужно использовать.


AVK>Это к вопросу о Плагин к Решарперу/Розлину
Автор: AndrewVK
Дата: 29.03.16

Угу. Но я боюсь что-либо обещать, т.к. пока у меня и свободного часа в сутки не набирается.
Re[7]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 20:15
Оценка:
Здравствуйте, Sinix, Вы писали:

AVK>>Что именно не работает?

S>Ассерты называются как каждый автор захочет и получается примерно то, что сейчас творится с ассертами в Nunit: часть obsolete, часть дублирует существующие и без справки в этом болоте не разберёшься

Ну вот я и предлагаю придумать правила именования хотя бы примерные.


AVK>>Я не предлагаю копировать оттуда методы, я предлагаю переименовать AssertArg в ArgRequires.

S>А есть доводы за?

Так уж принято — assert методы должны звучать как утверждение, исторически сложилось. У тебя же рядом NotNull именно такой. Не вижу причин отходить от этого правила.

S> Кроме довода "так сделано в code contracts"


Не только. В NUnit тоже самое (за исключением позже добавленногоь бардака, который ты упоминал).

S>AssertState, к примеру, ни разу не Invariant.


Почему? Набор утверждений о состоянии это инвариант и есть.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Assertions
От: Sinix  
Дата: 30.03.16 20:46
Оценка:
Здравствуйте, AndrewVK, Вы писали:


AVK>Ну вот я и предлагаю придумать правила именования хотя бы примерные.


Угу, сделаю. My bad, не подумал, что народу не хватит того, что добавил.



AVK>Так уж принято — assert методы должны звучать как утверждение, исторически сложилось. У тебя же рядом NotNull именно такой. Не вижу причин отходить от этого правила.

Ну как бы да, но есть случаи, когда это не ассерт в чистом виде, а заготовка для него.

Как раз недавно добавлял Code.DisposedIf()/Code.DisposedIfNull().

Почем так названо:

1. В большинстве реализаций dispose паттерна выставляется флаг disposed или просто обнуляется какое-то из полей.
Двойное отрицание вида
Code.NotDisposed(!disposed, GetType());

// или
Code.NotDisposed(file != null, GetType());
выглядит очень криво.

2. В 99% случаев такие заготовки не используются напрямую, а оборачиваются в хелпер. Хотя бы затем, чтоб не копировать сложную строку форматирования или сложное условие из метода в метод.
Вот так
protected void AssertNotDisposed() => Code.DisposedIf(disposed, this);
оно выглядит гораздо лучше.


S>>AssertState, к примеру, ни разу не Invariant.

AVK>Почему? Набор утверждений о состоянии это инвариант и есть.

Не, инвариант — это условие, которое должно соблюдаться всё время жизни объекта.

А state — это проверка, что мы находимся в состоянии, в котором можно вызывать конкретный метод.

Ну, например, для SqlConnection:
корректная строка соединения — инвариант.
есть открытое соединение — проверка нужна только перед выполнением запросов. Для остальных методов (например, для CreateCommand) она необязательна.
Re[9]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.03.16 20:51
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Не, инвариант — это условие, которое должно соблюдаться всё время жизни объекта.


Вовсе нет. Скоуп может быть любым — метод, цикл и т.п. Это в СС оно все время жизни.

In computer science, an invariant is a condition that can be relied upon to be true during execution of a program, or during some portion of it. It is a logical assertion that is held to always be true during a certain phase of execution. For example, a loop invariant is a condition that is true at the beginning and end of every execution of a loop.

Википедия.
Но, вобщем, тут не критично, можно и State. А вот Assert мне чисто эстетически не нравится — выглядит как объемный boilerplate, не несущий смысла. И так понятно, что раз уж мы класс Code написали, то дальше будет assert, нет смысла еще раз напоминать об этом.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[3]: Assertions
От: Sinix  
Дата: 30.03.16 20:57
Оценка:
Здравствуйте, AndrewVK, Вы писали:


S>>Вот тут надо подумать. Нам точно нужно запихивать специфичные ассерты именно в Code?

AVK>Диапазоны я бы не назвал специфичными.
... Вот этот ответ пропустил, сорри.

Ок, значит сделаю завтра
* NotNullNorEmpty для строк/массивов/коллекций, c проверками для enumerable потом определимся.
* NotNullNorWhiteSpace — пусть будет, раз надо
* ArgumentInRange/StateInRange + ValidIndex. Имена фиговые, так что если есть получше — велкам!

Ничего не пропустил?


Не в порядке спора

S>>1. NotNullNorWhiteSpace — нужен реальный юз-кейз. Я ещё не видел ни одного метода, в котором использовался бы такой ассерт.

AVK>Да вроде все очевидно, не? Мне такое регулярно попадается.

А можно пример?
А то я не могу сообразить, где допустима любая непустая строка, если она не из пробелов.
Re[10]: Assertions
От: Sinix  
Дата: 30.03.16 21:00
Оценка:
Здравствуйте, AndrewVK, Вы писали:


AVK>Но, вобщем, тут не критично, можно и State. А вот Assert мне чисто эстетически не нравится — выглядит как объемный boilerplate, не несущий смысла. И так понятно, что раз уж мы класс Code написали, то дальше будет assert, нет смысла еще раз напоминать об этом.


Мне тож не нравится, но способа лучше разделить методы "вот тебе готовая проверка для конкретного сценария" и "не нашёл? Ну вот тебе заготовка, допиливай" я не придумал
Re[3]: Assertions
От: rameel https://github.com/rsdn/CodeJam
Дата: 31.03.16 15:52
Оценка:
Здравствуйте, AndrewVK, Вы писали:

S>>Вот NotNullNorEmpty для строк/enumerable/массивов можно добавить.


Здесь согласен с Андреем, если проверять на Empty для IEnumerable, то равзе что только в дебаг засунуть. В своих проектах такое было сделано только для ICollection<T> и отдельно для массивов

S>>2. NotNullNorContainsNull — да, но это уже к продвинутым сценариям, хорошо бы в EnumerableCode запихнуть.


Здесь тоже, но только для IList<T>.

AVK>Тут спорно. Для enumerable лишняя итерация для проверки на empty — не айс. В 99% случаев лучше проверить в ходе основного энумерирования.


+1

По поводу NotNullNorContainsNull для IList<T>, то в ряде случаев, когда в конструктор передается enumerable, то обычно он материализуется в массив ну или список для более быстрого доступа позже, а как таковое итерирование происходит именно потом, не в конструкторе, и вот тогда может вылететь NRE.

Это вариация на тему инвариантов на вроде ForAll(v => v != null).

S>>пойдёт. StateInRange не добавлять, если реального сценария нет.


AVK>Ну, если уж озабочиваться проверками инвариантов, то сценарий вполне реален.


+1
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: Assertions
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 31.03.16 18:20
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Если серьёзно — мой косяк, не ожидал, что интерес будет.


Догфудинг пока никто не отменял. И поддержка решарпером тут тоже была бы крайне полезна.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: аллокации для params object[]
От: Sinix  
Дата: 25.04.16 11:12
Оценка:
Здравствуйте, Jack128, Вы писали:

J>чтоб убрать лишнее выделение памяти под массив.

Гхимм, а оно разве не учтено в рослине?

Когда проверял — работало. В перфтесты добавлю.
Re[3]: аллокации для params object[]
От: Jack128  
Дата: 25.04.16 11:23
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Jack128, Вы писали:


J>>чтоб убрать лишнее выделение памяти под массив.

S>Гхимм, а оно разве не учтено в рослине?

Вроде тут про Array.Empty говорится, то есть про случай, когда нет аргументов для форматирования. А я говорю, про случай, когда мы передаем один аргумент для форматирования.
Собственно у любого логера так сделано.

Log(string message);
Log(string message, object arg);
Log(string message, object arg1, object arg2);
Log(string message, object arg1, object arg2, object arg3);
Log(string message, params object [] args);


Если совсем замарочиться, то нужно вообще дженерик методы делать, а-ля
Log<TArg>(string message, TArg arg);
Log<TArg1, TArg2>(string message, TArg1 arg1, TArg2 arg2);
...
Log(string message, params object [] args);

это уже чтоб боксинг убрать, когда value-типы передаем
Re[4]: аллокации для params object[]
От: Sinix  
Дата: 25.04.16 11:27
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Если совсем замарочиться, то нужно вообще дженерик методы делать, а-ля

А, не так вопрос понял

Ну да, надо сделать генерик-версию, чтоб без боксинга. И перегрузки до 4 аргументов. И допилить вот этот
Автор: Sinix
Дата: 19.04.16
момент в решарпере. И губозакаточную машинку пожалуйста.
Я вот думаю: дадут мне под это дело прикрутить отдельный проект с реврайтером на рослине, геройски копипастить копипасту, или всё-таки попытать счастья с парсингом регексами?

Есть какие идеи?
Re[5]: аллокации для params object[]
От: Jack128  
Дата: 25.04.16 17:39
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Jack128, Вы писали:


J>>Если совсем замарочиться, то нужно вообще дженерик методы делать, а-ля

S>А, не так вопрос понял

S>Ну да, надо сделать генерик-версию, чтоб без боксинга. И перегрузки до 4 аргументов. И допилить вот этот
Автор: Sinix
Дата: 19.04.16
момент в решарпере. И губозакаточную машинку пожалуйста.

S>Я вот думаю: дадут мне под это дело прикрутить отдельный проект с реврайтером на рослине, геройски копипастить копипасту, или всё-таки попытать счастья с парсингом регексами?

S>Есть какие идеи?


Э, моя не понимать. Для чего именно нужен рерайтер на рослине?
типа по коду

public static void AssertArgument(
bool condition,
[NotNull, InvokerParameterName] string argName,
[NotNull] string messageFormat,
[CanBeNull] params object[] args)
{
if (!condition)
throw CodeExceptions.Argument(argName, messageFormat, args);
}

генерить набор перегрузок с один, двумя и тд аргументами??
Re[6]: аллокации для params object[]
От: Sinix  
Дата: 25.04.16 17:53
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Э, моя не понимать. Для чего именно нужен рерайтер на рослине?

J>генерить набор перегрузок с один, двумя и тд аргументами??

Ну да. Я как бы альтернатив для сделать один раз и хорошо не вижу.

Задача: на входе исходник, на выходе — partial-класс с перегрузками для методов с params object[] args в конце.

На параметры метода могут быть навешены атрибуты, могут использоваться default values, default value может быть произвольной строкой, для каждой перегрузки надо адаптировать xdoc comments — из них справка генерируется.

Вот не хочу я такое регэксом парсить
Эта штука не один раз нужна, навскидку методов 5 похожих точно найдётся.
Re[7]: аллокации для params object[]
От: Jack128  
Дата: 25.04.16 19:18
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Jack128, Вы писали:


J>>Э, моя не понимать. Для чего именно нужен рерайтер на рослине?

J>>генерить набор перегрузок с один, двумя и тд аргументами??

S>Ну да. Я как бы альтернатив для сделать один раз и хорошо не вижу.


S>Задача: на входе исходник, на выходе — partial-класс с перегрузками для методов с params object[] args в конце.


S>На параметры метода могут быть навешены атрибуты, могут использоваться default values, default value может быть произвольной строкой, для каждой перегрузки надо адаптировать xdoc comments — из них справка генерируется.

default values в методах с params ? Это как?

S>Вот не хочу я такое регэксом парсить

S>Эта штука не один раз нужна, навскидку методов 5 похожих точно найдётся.

Ну я б таки регэксп заюзал, в целевых методах не будет супер сложного кода, так что никаких колизий быть не должно.
Re[8]: аллокации для params object[]
От: Jack128  
Дата: 25.04.16 19:42
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Sinix, Вы писали:


S>>Эта штука не один раз нужна, навскидку методов 5 похожих точно найдётся.


AVK>Ага, в GetValueOrDefault например. После последних правок там 18 перегрузок. 18, Карл!


Кстати, как на счет заменить
TValue GetValueOrDefault<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)

на
TResult GetValueOrDefault<TKey, TValue, TResult>([NotNull] this IDictionary<TKey, TValue> dictionary, TKey key, TResult defaultValue)
    where TValue: TResult


Смысл в том, что иногда у нас есть на например словарь Dictionary<int, List<MyClass>>, а в качестве дефолотового значения мы хотим задать IReadOnlyList<MyClass>
Re[8]: аллокации для params object[]
От: Sinix  
Дата: 25.04.16 20:15
Оценка:
Здравствуйте, Jack128, Вы писали:


S>>На параметры метода могут быть навешены атрибуты, могут использоваться default values, default value может быть произвольной строкой, для каждой перегрузки надо адаптировать xdoc comments — из них справка генерируется.

J>default values в методах с params? Это как?
Ну вот так вот например:
http://stackoverflow.com/a/13807929/318263


S>>Вот не хочу я такое регэксом парсить

S>>Эта штука не один раз нужна, навскидку методов 5 похожих точно найдётся.



J>Ну я б таки регэксп заюзал, в целевых методах не будет супер сложного кода, так что никаких колизий быть не должно.


Ты похоже всю засаду с задачей не заметил.

Надо
1. Из готового исходника выцепить вcе методы с params. Хотя бы заголовки, от первого комментария к методу и до первого операнда. Атрибуты и комментарии важны.
2. В коде каждого метода заменить params на n параметров. Добавить генерик-параметры.
3. Заменить тело метода на вызов исходной перегрузки.
4. Поправить xml-документацию.

Регексами? вот чего-то я сомневаюсь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.