C # Многократная аналогичная проблема перегрузки - PullRequest
0 голосов
/ 27 января 2010

Сценарий

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

Выпуск

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

Вопрос

Как мне обойти эту проблему, чтобы следующий код компилировался?

Код

    public RateInstrument(string ric, string tenor)
    {
        Ric = ric;
        Tenor = tenor;
    }

    public RateInstrument(string ric, string date)
    {
        Ric = ric;
        Date = ConvDate(date);
    }

Ответы [ 9 ]

4 голосов
/ 27 января 2010

Измените второе, чтобы принять дату. Это право, и это право.

3 голосов
/ 27 января 2010

(я предполагаю, что действительно имеет смысл принимать дату в виде строки, и это "ric" означает что-то в вашем домене. Это, безусловно, достаточно общая проблема.)

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

private static RateInstrument(string ric, string tenor, string date)
{
    ...
}

public static RateInstrument FromRicAndTenor(string ric, string tenor)
{
    return new RateInstrument(ric, tenor, null);
}

public static RateInstrument FromRicAndDate(string ric, string date)
{
    return new RateInstrument(ric, null, date);
}

Преимущества статических методов построения:

  • Не всегда нужно возвращать новый экземпляр (может применяться пул и т. Д.)
  • Может вернуть ноль, если это действительно полезно
  • Может выполнять полезную работу до и после строительства легче, чем конструктор

Недостатки:

  • выглядит странно, когда вы привыкли называть "новым"
  • Наследование может стать более сложным (вам, по крайней мере, нужно сделать конструктор защищенным для не вложенных производных типов)

(Оба из них страдают от недостатка инъекций, по сравнению с экземплярами методов на реальном заводском типе, конечно.)

2 голосов
/ 27 января 2010

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

public RateInstrument(string ric, string tenor, string date)
{
    Ric = ric;
    if (!string.IsNullOrEmpty(tenor))
    {
            Tenor = tenor;
    }

    if (!string.IsNullOrEmpty(date))
    {
        Date = ConvDate(date);
    }
}
1 голос
/ 27 января 2010

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

    public RateInstrument(string ric, string tenor) 
{ 
    Ric = ric; 
    Tenor = tenor; 
} 

public RateInstrument(string ric, TypeOfDate date) 
{ 
    Ric = ric; 
    Date = date; 
} 
1 голос
/ 27 января 2010

Имеют две разные функции:

RateInstrumentFromDate (мля, дата)

RateInstrumentFromTenor (мля, тенор)

0 голосов
/ 27 января 2010

У вас не может быть двух методов с одинаковой подписью . Подпись состоит из:

  • Наименование метода
  • Количество параметров
  • Типы данных и порядок параметров
  • Модификаторы параметров

ПРИМЕЧАНИЕ. Тип возвращаемого значения - , а не часть подписи. Кроме того, важны типы и порядка параметров, а не их имена.

Возможно, вы захотите изменить тип данных параметра, который принимает string date, чтобы взять DateTime объект вместо строки. Это изменит сигнатуру второго метода.

0 голосов
/ 27 января 2010

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

  1. Измените параметр даты из строки на соответствующий объект Date, чтобы различать две подписи.

  2. Используйте один и тот же конструктор для обоих и используйте что-то по линии DateTime.TryParse, чтобы определить, является ли второй аргумент датой или тенором.

  3. Используйте фабричные методы вместо конструктора, чтобы они могли называться по-разному.

Идеи 1 и 3 предполагают, что вызывающий код знает кое-что о том, какой тип объекта вы пытаетесь создать. Идея 2 позволяет классу оставаться родовым и решать самому.

Только мои 2 ¢ по теме.

0 голосов
/ 27 января 2010

Создайте два статических метода, которые создадут объект для вас:

static RateInstrument NewRateInstrumentByTenor(string ric, string tenor) {
   return new RateInstrument {
      Ric = ric,
      Tenor = tenor
   }
}
static RateInstrument NewRateInstrumentByDate(string ric, string date) {
   return new RateInstrument {
      Ric = ric,
      Date = ConvDate(date)
   }
}
0 голосов
/ 27 января 2010

Вам нужно дать этим двум конструкторам разные подписи, на данный момент они оба

foo(string, string);

Иначе как вы (не говоря уже о компиляторе) узнаете, какой метод вы намеревались вызвать?

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

public RateInstrument(string ric, string tenor, string date)
public RateInstrument(string ric, DateTime date)

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

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

...