Есть ли лучший способ написать функцию C #, которая принимает несколько типов? - PullRequest
0 голосов
/ 09 января 2012

Некоторый контекст: я хотел бы написать класс, в котором основной метод добавления объектов в коллекцию - это метод (или методы) с именем Add (или что-то в этом роде). И поэтому подпись, которая кажется лучшей, это params object []. Внутренне эта функция должна переключать / если-либо все типы, которые она может принимать. Таким образом, первоначально он мог принять этот массив object [], но мне бы хотелось, чтобы он также принимал object [] [], object [] [] [] и т. Д., А затем метод / функция могли бы сгладиться внутри, поэтому пользователю не нужно делать это до вызова этой функции.

Итак ...

Можно ли написать функцию, которая может принимать различные типы уровней списка для одного типа объекта? В качестве дополнительного вопроса при проектировании интерфейса к классу, который лучше принять object[] или IEnumerable<object> или params object[]? (Правка: вычеркнуто из вопроса, потому что уже происходит достаточно .)

Например, я имею в виду функцию, которая принимает оба / все из object[], IEumerable<object> и, возможно, дальнейшее вложение, например: IEnumerable<IEnumerable<object>>, object[][] (и так далее, и так далее) .

Возможно ли это?

Ответы [ 4 ]

16 голосов
/ 09 января 2012

Вы заметите, что сам класс List<T> имеет методы Add, которые принимают T и AddRange, который принимает последовательность T. Мы не пытаемся перегрузить Add, чтобы сделать оба, по двум причинам.Во-первых, потому что добавление чего-либо и добавление нескольких вещей логически различны, а во-вторых, потому что это значительно усложняет разрешение перегрузки.

Если вам нужен метод, который принимает последовательность T, то напишите метод, который принимаетпоследовательность T. Если у вызывающей стороны есть последовательность последовательностей, заставьте их сгладить ее;не пытайтесь угадать от их имени, как это сделать эффективно.

, что лучше: принять object[] или IEnumerable<object> или params object[]?

Как же мы должны знать?Мы не те, кто вызывает метод.Человек, которого вы должны спросить, - это человек, который собирается писать код для вызова вашего метода.

2 голосов
/ 09 января 2012

Один из вариантов - просто создать одну функцию, а затем перегрузить ее столько раз, сколько вам нужно. Вы можете заставить перегруженные функции вызывать «базовую» функцию.

DoWork(params object[] args)
{
  //do the actual work
}

DoWork(IEnumerable<object> args)
{
  DoWork(args.ToArray());
}

//etc etc
1 голос
/ 09 января 2012

Это зависит от того, что вы подразумеваете под типами списков. Если вы подразумеваете это явно, то у вас может быть метод, который принимает IList<T>. Если вы хотите добавить массивы в микс, тогда вы действительно должны принять IEnumerable<T>. Если вам не нужно изменять его, в этом случае массивы не будут работать, поэтому вы можете принять ICollection<T>.

1 голос
/ 09 января 2012

Выполните две перегрузки одной функции: одну, которая принимает IEnumerable<T>, и одну, которая принимает params T[]. Реализуйте последнее, позвонив первым. Забудьте о вложенности, LINQ может легко выравнивать коллекции, используя SelectMany.

...