Переменное количество аргументов, не упаковывая типы значения?

Питание два будет иметь всего один набор битов (для неподписанных чисел). Что-то как

bool powerOfTwo = !(x == 0) && !(x & (x - 1));

будет хорошо работать; меньше, чем питание два составляют всю 1 с в менее значимых битах, так должен И к 0 поразрядно.

, Поскольку я принимал неподписанные числа, == 0 тестов (что я первоначально забыл, извините) соответствует. Можно хотеть a> 0 тестов при использовании целых чисел со знаком.

10
задан Jon Seigel 27 February 2010 в 03:51
поделиться

4 ответа

Вы можете использовать обобщенные шаблоны:

public void DoSomething<T>(params T[] args)
{
}

Однако это позволит указать только один тип ValueType. Если вам нужно смешивать или сопоставлять типы значений, вам придется разрешить использование боксов, как вы делаете сейчас, или предоставить определенные перегрузки для разного количества параметров.


Изменить: если вам нужно более одного типа параметр, вы можете в некоторой степени использовать для этого перегрузки.

public void DoSomething<T,U>(T arg1, params U[] args) {}
public void DoSomething<T,U>(T arg1, T arg2, params U[] args) {}

К сожалению, это требует наличия нескольких перегрузок для ваших типов.

В качестве альтернативы вы можете напрямую передавать массивы:

public void DoSomething<T,U>(T[] args1, U[] args2) {}

Вы теряете красивый синтаксис компилятора , но тогда вы можете передать любое количество обоих параметров.

13
ответ дан 3 December 2019 в 20:42
поделиться

В настоящее время нет, нет, и я не видел ничего, посвященного этой проблеме, в выпущенной информации .NET 4 .

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

Я задаюсь вопросом: действительно ли проблема производительности, или вы преждевременно оптимизируете?

3
ответ дан 3 December 2019 в 20:42
поделиться

Предположим, код, из которого вы вызываете этот метод, знает типы аргументов. Если это так, вы можете упаковать их в соответствующий тип Tuple из .NET 4 и передать его экземпляр (Tuple - ссылочный тип) такому методу, как объект (поскольку нет общей базы для всех кортежей).

Основная проблема здесь в том, что нелегко обработать аргументы внутри этого метода без упаковки / распаковки и, вероятно, даже без отражения. Попробуйте подумать, что нужно сделать, чтобы извлечь, скажем, N-й аргумент без бокса. В конечном итоге вы поймете, что вам нужно либо иметь дело с поиском в словаре (с использованием обычных Dictionary или внутренних словарей , используемых CLR), либо заниматься боксом. Очевидно, что поиск по словарю намного дороже.

Я пишу это, потому что на самом деле мы разработали решение для очень похожей проблемы: мы должны иметь возможность работать с нашими собственными кортежами без упаковки - в основном, для их сравнения и десериализации (кортежи используются движок базы данных, который мы разрабатываем, поэтому выполнение любой базовой операции действительно важно в нашем случае).

Но:

  • Мы получаем довольно сложное решение. Взгляните, например, на TupleComparer .
  • Эффект от отсутствия упаковки на самом деле не так хорош, как мы ожидали: каждая операция упаковки / распаковки заменяется индексированием одного массива и несколькими вызовами виртуальных методов, стоимость обоих способов практически идентичны.

Единственное преимущество разработанного нами подхода состоит в том, что мы не «засыпаем» Gen0 мусором, поэтому коллекции Gen0 происходят гораздо реже. Поскольку стоимость сбора Gen0 пропорциональна пространству, выделяемому «живыми» объектами, и их количеству, это дает заметное преимущество, если другие распределения смешиваются (или просто происходят во время) выполнения алгоритма, который мы пытаемся оптимизировать таким образом.

Результаты: после этой оптимизации наши синтетические тесты показали прирост производительности от 0% до 200-300%; с другой стороны, простой тест производительности самого движка базы данных показал гораздо менее впечатляющее улучшение (около 5-10%). Много времени было потрачено впустую на вышеперечисленных уровнях (есть также довольно сложная ORM), но ... Скорее всего, это то, что вы действительно увидите после реализации подобных вещей.

Короче, я советую вам сосредоточиться на что-то другое. Если будет ясно, что это серьезная проблема производительности вашего приложения,

3
ответ дан 3 December 2019 в 20:42
поделиться

В C # 4.0 вы можете использовать именованные (и, следовательно, необязательные) параметры! Дополнительная информация о в этом сообщении в блоге

-1
ответ дан 3 December 2019 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: