2015-04-21 4 views
5

Я программировал для летних лет сначала Delphi, а теперь C#, поэтому я думал, что знаю, как работает перегруженный метод, но, видимо, нет.Как работают перегруженные методы

Первый некоторый код

public enum TestEnum { Option1, Option2, Option3 } 

public class Setting 
{ 
    public Setting() 
    { 
     AddSettings(); 
    } 

    protected void CreateSetting<TEnum>(string AName, TEnum AValue) where TEnum : struct, IComparable, IFormattable 
    { 
     //do stuff 
    } 

    protected void CreateSetting(string AName, string AValue) 
    { 
     //do stuff 
    } 

    protected void CreateSetting(string AName, int AValue) 
    { 
     CreateSetting(AName, AValue.ToString()); 
    } 

    protected void AddSettings() 
    { 
     CreateSetting("Language", (byte)0); //#1 
     CreateSetting("BFL", "true"); //#2 
     CreateSetting<TestEnum>("TestEnum", TestEnum.Option1); //#3 
     CreateSetting("TestEnum", TestEnum.Option1); //#4 
    } 
} 

Я добавил номер для каждого вызова CreateSettings для того, чтобы сделать это easyer объяснить.

Мой вопрос:

вызов # 1 вызывает неправильную (Generic) версию CreateSettings, потому что я сделал бросок к byte, но почему?

Звоните # 2 работает нормально.

Звоните # 3 работает отлично. Я явным образом назову версию gerneric

Звонок # 4 также работает, но с некоторой «магии» компилятор разрешает правильную (genneric) версию и вызывает это. Но почему это работает?

Я понял, что # 1 вызывает неправильную версию по той же причине, что и # 4. Мне просто интересно, может ли кто-нибудь дать мне объяснение.

+0

Предположительно, какую версию .Net framework/Visual studio вы используете для этого? –

ответ

10

Перегрузки работают, как и ожидалось, вы заявили, что:

# 1 вызывает неправильную версию

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

вызов # 4 также работает, но с некоторыми «магии»

Это не магия, это работает в основном из-за той же причине, что и выше, тип не является ни int или string, так единственная возможная перегрузка он может назвать это родовой один, потому что ваш «универсальным» метод, по существу, говорит любой другой класс (тип здесь TestEnum)

+0

Звонок # 1 вызывает общую перегрузку, так как есть преобразование между перечислением и байтом – VMAtm

+0

ok "wong" Я имел в виду разные, чем я ожидал. ans yes Я ожидал, что он попадет в версию int, потому что я не знал, что №4 является допустимым синтаксисом. Я получил идею для этого, когда # 1 назвал «неправильную» версию. –

+1

@VMAtm Он вызывает общую перегрузку, потому что она не является ни строкой, ни 'int' – mattytommo

2

метод называется определяется процессом разрешения перегрузки.

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

https://msdn.microsoft.com/en-us/library/aa691339%28v=vs.71%29.aspx

Общий процесс разрешения перегрузки описан здесь:

https://msdn.microsoft.com/en-us/library/aa691336%28v=vs.71%29.aspx

Следуя по этим правилам и по сравнению с каждым из ваших сценариев вы должны быть в состоянии чтобы увидеть, какое правило вы нажимаете в каждом случае.

1

вызов # 1

Вы сделали ограничение где TEnum: структура, IComparable, IFormattable

Что означает тип TEnum либо тип значения или тип, который реализует два интерфейса у вас есть байт аргумент, который означает, что метод, который будет вызываться метод является 1, так как байт является типом значения, и ни один из других методов не принимает байт в качестве аргумента

Вызов 2 и Call3

Работы, как и ожидалось

Call4

Опять компилятор разрешит первому методу, поскольку Enum является типом значения, и ни один из другого метода не принимает тип Enum в качестве аргумента так наиболее подходящей перегрузкой является метод 1

+1

Ваше объяснение для вызова # 1 неверно, поскольку ограничения не являются частью подписи. См. Это: http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx. Вызов # 1 вызывает общий метод, поскольку он является единственным кандидатом слева (байт не является int или строкой). – Maarten

+0

То, что я имел в виду, он видит все возможности, и поскольку байт является типом значений, он будет идти первым методом, если бы он был классом вместо структуры, он дал бы вам ошибку времени компиляции – Coder1409

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