Как вызвать перегруженные методы, имеющие необязательные параметры, без неоднозначности для компилятора? - PullRequest
3 голосов
/ 17 июля 2011

У меня есть статическая функция в классе с двумя перегрузками. Обе перегрузки одинаковы, за исключением одного или двух параметров. string body - единственный необходимый параметр в моей функции, который вы можете видеть, остальные - необязательные параметры. Но параметры object y и int x не должны объединяться. Поэтому мне пришлось написать две перегрузки, как показано ниже. Я предоставляю образец кода:

    public static void Foo(string body, string caption = "", int x = 0)
    {
        //leave it to me
    }

    public static void Foo(string body, string caption = "", object y = null)
    {
        //leave it to me
    }

Теперь, когда я хочу вызвать эту статическую функцию из других классов, поскольку string body является единственным обязательным параметром, я стараюсь время от времени писать:

ClassABC.Foo("hi there");

Что дает мне это: The call is ambiguous between the following methods or properties. Я знаю, почему это происходит, и что в идеале является решением. Но мне нужно знать, можно ли что-то еще сделать в C # для решения этой проблемы.

Очевидно, что компилятор не понимает, какую функцию выбрать, но я не возражаю против того, чтобы компилятор рассматривал обе функции без int x и object y. Три вопроса в основном:

  1. Есть ли какой-либо способ сказать компилятору "взять что-нибудь" (почти невыполнимая задача, но все же сообщите мне)?

  2. Если нет, могу ли я создать одну функцию для обоих случаев? Примерно так:

    public static void Foo(string body, string caption = "", int x = 0 || object y = null) // the user should be able to pass only either of them!
    {
        //again, I can handle this no matter what
    }
    
  3. Есть ли другие способы решения этой проблемы?

РЕДАКТИРОВАТЬ:

  1. Я не могу переименовать две функции.

  2. Не могу создать больше перегрузок. Возможны не только эти комбинации. Я должен быть в состоянии написать Foo(string body, int x) и т. Д. Так идет. Практически невозможно справиться со всеми условиями, если параметры больше, чем, скажем, 10 !. Короче говоря, необязательные параметры обязательны.

Ответы [ 4 ]

5 голосов
/ 17 июля 2011

Добавить отдельную перегрузку для обработки случаев с одним или двумя аргументами.

public static void Foo(string body, string caption = "")
{
} 

public static void Foo(string body, string caption, int x)
{
}

public static void Foo(string body, string caption, object y)
{
}

Если вам нужно обработать произвольные комбинации аргументов, возможно, пришло время сгруппировать необязательные аргументы в собственный класс:

public sealed class Options
{
    public string Caption { get; set; }
    public int X { get; set; }
    public object Y { get; set; }
}

public static void Foo(string body, Options options)
{

} 
5 голосов
/ 17 июля 2011

Если вы не уверены, сделайте это безопасным способом.

public static void Foo(string body)
{
}

public static void Foo(string body, string caption)
{
}

public static void Foo(string body, string caption, int x)
{
}

public static void Foo(string body, string caption, object y)
{
}

РЕДАКТИРОВАТЬ: Поскольку вы упомянули, что может быть около 10 параметров, вам нужно более общее решение.

Существует опция с переменными аргументами. Проверьте тип каждого аргумента и действуйте соответственно:

public static void Foo(string body, param object[] the_rest_of_arguments)
{
}

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

public class FooArguments
{
    public string caption;
    public int x;
    public object y;
}

public static void Foo(string body, FooArguments the_rest_of_arguments)
{
}

Вместо нового класса FooArguments вы можете иметь Dictionary<string,object>, где ключ - это имя аргумента, а значение - сам аргумент.

Если функция вызывается с неподходящей комбинацией аргументов, просто сгенерируйте исключение.

1 голос
/ 17 июля 2011

Как насчет реализации только второго варианта и проверки фактического типа «объекта», передаваемого в качестве третьего параметра (если вообще есть), с использованием GetType()? Это, однако, предполагает, что пропуск третьего параметра (x = 0 или y = null) приведет к тем же результатам. Обратите внимание, что этот подход предлагает меньше возможностей для оптимизации, поскольку выбор должен происходить во время выполнения, а не во время компиляции (если только компилятор не может это различить).

1 голос
/ 17 июля 2011

предоставить упаковку

public static void Foo (тело строки)

{

   public static void Foo(string body,  "", null);
  //leave it to me

}

или что-то похожее

...