Как справляться с конфликтами в сигнатурах перегруженных методов?

У меня такое чувство, что этот вопрос - банка червей, но я все равно спрошу... :)

У меня есть метод:

private MembershipUser GetUserFromReader(SqlDataReader reader)

И я хочу перегрузить этот метод другим типом возвращаемого значения:

private User GetUserFromReader(SqlDataReader reader)

Но компилятор жалуется, что эти два метода имеют одинаковую сигнатуру.

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

Я играл с идеей сделать что-то вроде:

private User GetUserFromReader(T reader)

Но еще не исследовал это полностью. Похоже, мне нужно внести кучу изменений в то, как я использую свой объект для чтения.

Любые идеи? Что лучше всего делать, когда у вас есть два перегруженных метода с одной и той же сигнатурой?

Спасибо за помощь...


person Peter    schedule 10.02.2010    source источник
comment
Есть ли причина, по которой вы не можете просто переименовать частный метод? Не то чтобы это затрагивало внешних пользователей вашего класса — в конце концов, это личное.   -  person Matt Hamilton    schedule 11.02.2010
comment
да, согласен. что получил мой ответ :)   -  person Peter    schedule 11.02.2010


Ответы (5)


Зачем его перегружать? Почему бы просто не позволить методу сказать, что он делает, например:

private MembershipUser GetMembershipUserFromReader(SqlDataReader reader)
private User GetUserFromReader(SqlDataReader reader)
person Luhmann    schedule 10.02.2010
comment
Спасибо. Я действительно не думал о доступности, когда задавал вопрос. Я думаю, что это лучшее решение в этом случае, потому что оно «частное». - person Peter; 11.02.2010

Если вы действительно хотите различать тип возвращаемого значения, но использовать одну и ту же сигнатуру метода, вы можете использовать дженерики:

private T GetUserFromReader<T>(SqlDataReader reader)

Но гораздо проще просто переименовать методы, как в ответе Лумана.

person Robert Harvey    schedule 10.02.2010
comment
Спасибо пачка. Я попробую, когда столкнусь с той же ситуацией с общедоступными методами. В этом случае, поскольку это личное, я согласен, что ответ Лумана - лучшее решение. - person Peter; 11.02.2010

Ваши единственные реальные варианты:

  1. Изменить название функции
  2. Изменить сигнатуру функции

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

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

person Adam Robinson    schedule 10.02.2010

Вы не можете изменить возвращаемый тип при перегрузке. Как компилятор должен сказать, какой из них вы хотите использовать?

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

Либо так, либо называйте методы по-разному, поскольку они явно делают разные вещи.

person Anon.    schedule 10.02.2010

Простой ответ заключается в том, что с точки зрения C# вы не можете. Перегрузка по возвращаемому типу разрешена (я думаю) в MSIL, но не в C#.

Единственный реальный выбор (т. е. исключающий добавление «фиктивного» параметра) — это вызвать один метод GetMembershipUserFromReader, а другой — GetUserFromReader.

person Rob    schedule 10.02.2010
comment
Правильный; CLR позволяет перегрузкам различаться только по типу возвращаемого значения. Существует ряд тонких различий между правилами C# для сопоставления подписей и правилами CLR; это самое очевидное. - person Eric Lippert; 11.02.2010
comment
@Eric: Вы знаете, почему это реализовано в CLR? Я думал, что в некоторых случаях это может быть полезно в C#, но мои коллеги со мной не согласились. Но для меня имеет смысл перегружать возвращаемый тип там, где он не двусмысленный. Как вы думаете, Эрик? - person Joan Venge; 11.02.2010
comment
@Joan: В языке MSIL нет такого понятия, как разрешение перегрузки. Каждый метод (или слот виртуального метода) имеет уникальный токен, и вызов метода в значительной степени просто вызывает метод, связанный с этим токеном. Поскольку нет необходимости выполнять разрешение перегрузки на основе аргументов, возвращаемый тип может быть частью подписи. - person Eric Lippert; 11.02.2010