2014-10-22 2 views
2

Скажем, у меня есть следующие две функции:По умолчанию перегрузки неоднозначных вызовов

void Foo(IEnumerable<string> bar) 
{ 
    if(bar == null) 
    return; 
    foreach(var b in bar) 
    { 
    Console.Write(b); 
    } 
}  

и

void Foo(string bar) 
{ 
    Foo(new string[] { bar }); 
} 

Те два неоднозначны, если я передаю null в качестве параметра.

Есть ли способ намекнуть на компилятор, чтобы устранить перегрузку? Любой атрибут или директива или что-то еще? В этом случае я бы хотел, чтобы первая функция вызывалась. Что-то вроде:

[InCaseOfAmbiguityUseThis] 
public void Foo(IEnumerable<string> bar) 

Так что, если я Foo(null) компилятор будет знать, где искать и не жалуются.

Я искал какое-то время и не нашел ничего уважения.

PS: Я знаю, что я могу использовать: Foo((IEnumerable<string>)null), но это то, что я пытаюсь избежать: типов в реальных функциях достаточно долго и использовать общие ограничения (так что я не могу просто наследовать тип, чтобы сделать он короче), так что он много кодирует код.

Я не против иметь 'dirty' в библиотеках (где я указываю эти функции), но не в фактическом бизнес-коде (где я называю эти функции).

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

Редактировать

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

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

Task<IEnumerable<TResult>> GetAsyncProjected<TResult>(
    IEnumerable<Expression<Func<T, bool>>> filters, 
    Expression<Func<T, TResult>> projection, 
    IEnumerable<string> eagerLoadRelationships, 
    CancellationToken cancellationToken, 
    ServiceRefreshMode refreshMode); 

Task<IEnumerable<TResult>> GetAsyncProjected<TResult>(
    Expression<Func<T, bool>> filter, 
    Expression<Func<T, TResult>> projection, 
    IEnumerable<string> eagerLoadRelationships, 
    CancellationToken cancellationToken, 
    ServiceRefreshMode refreshMode); 

// ... plenty of overloads for each possible parameter ... 

У меня есть еще один перегрузки для каждого из них перегрузки без параметра filter/filters, но я бы предпочел не делать так, чтобы вызывающий абонент знал, что он пропускает null для фильтра.

Если нет никакой возможности, то я буду искать другие пути (назвав его GetAsyncFilteredProjected(), если он имеет параметр или что-то)

+0

Нет, нет. Это просто двусмысленно, если вы используете нулевой литерал при вызове метода. Подумайте, почему вы так часто передаете нулевой литерал. Возможно, вам нужна безпараметрическая перегрузка. –

+1

Другой возможной альтернативой является объявление методов как 'params string []', что позволяет вызывающему абоненту поставлять любое количество строк в строке, в том числе и ничто (с недостатком, который вы не можете передать ему «IEnumerable» без сначала выполнив '.ToArray()'). –

+0

@JeroenMostert, который был бы действителен только в том случае, если параметр является последним параметром функции (в «реальном» случае это не так) – Jcl

ответ

3

Там нет никакого способа, чтобы настроить перегрузки в C#, как это. Существуют строгие правила выбора метода перегрузки.

Однако, если вы хотите, чтобы обеспечить версию метода без аргумент, вы можете просто создать новую перегрузку вместо передачи null:

void Foo() 
{ 
    Foo((string)null); 
} 

Было бы более удобным для чтения, в качестве бонуса ,

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

+0

Вот что я делаю сейчас, это именно то, чего я хочу избежать – Jcl

+1

@Jcl Неясно, создаете ли вы перегрузки или бросаете нуль в определенные типы при вызове методов. Первый способ - это * способ избежать двусмысленности в C#. – Athari

+0

Я уже делаю безпараметрическую перегрузку. В этом конкретном случае я бы предпочел не иметь безпараметрическую перегрузку, но если это невозможно, то пусть будет так. Во всяком случае, вопрос был ясен: можно ли намекнуть компилятору на автоматическое устранение неоднозначности? Если это невозможно, тогда я знаю все «обходные пути». – Jcl

Смежные вопросы