Основы программирования на C#

       

Преобразования внутри арифметического типа


Арифметический тип, как показано в таблице 3.1, распадается на 11 подтипов. На рис. 4.1 показана схема преобразований внутри арифметического типа.


Рис. 4.1.  Иерархия преобразований внутри арифметического типа

Диаграмма, приведенная на рисунке, позволяет ответить на ряд важных вопросов, связанных с существованием преобразований между типами. Если на диаграмме задан путь (стрелками) от типа А к типу В, то это означает существование неявного преобразования из типа А в тип В. Все остальные преобразования между подтипами арифметического типа существуют, но являются явными. Заметьте, что циклов на диаграмме нет, все стрелки односторонние, так что преобразование, обратное к неявному, всегда должно быть задано явным образом.

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

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

Понятие перегрузки методов и операций подробно будет рассмотрено в последующих лекциях (см. лекцию 8).

Диаграмма, приведенная на рис. 4.1, и в этом случае помогает понять, как делается выбор. Пусть существует две или более реализации перегруженного метода, отличающиеся типом формального аргумента. Тогда при вызове этого метода с аргументом типа T может возникнуть проблема, какую реализацию выбрать, поскольку для нескольких реализаций может быть допустимым преобразование аргумента типа T в тип, заданный формальным аргументом данной реализации метода. Правило выбора реализации при вызове метода таково: выбирается та реализация, для которой путь преобразований, заданный на диаграмме, короче. Если есть точное соответствие параметров по типу (путь длины 0), то, естественно, именно эта реализация и будет выбрана.

Давайте рассмотрим еще один тестовый пример. В класс Testing включена группа перегруженных методов OLoad с одним и двумя аргументами. Вот эти методы:

/// <summary> /// Группа перегруженных методов OLoad /// с одним или двумя аргументами арифметического типа. /// Если фактический аргумент один, то будет вызван один из /// методов, наиболее близко подходящий по типу аргумента. /// При вызове метода с двумя аргументами возможен /// конфликт выбора подходящего метода, приводящий /// к ошибке периода компиляции. /// </summary> void OLoad(float par) { Console.WriteLine("float value {0}", par); } /// <summary> /// Перегруженный метод OLoad с одним параметром типа long /// </summary> /// <param name="par"></param> void OLoad(long par) { Console.WriteLine("long value {0}", par); } /// <summary> /// Перегруженный метод OLoad с одним параметром типа ulong /// </summary> /// <param name="par"></param> void OLoad(ulong par) { Console.WriteLine("ulong value {0}", par); } /// <summary> /// Перегруженный метод OLoad с одним параметром типа double /// </summary> /// <param name="par"></param> void OLoad(double par) { Console.WriteLine("double value {0}", par); } /// <summary> /// Перегруженный метод OLoad с двумя параметрами типа long и long /// </summary> /// <param name="par1"></param> /// <param name="par2"></param> void OLoad(long par1, long par2) { Console.WriteLine("long par1 {0}, long par2 {1}", par1, par2); } /// <summary> /// Перегруженный метод OLoad с двумя параметрами типа /// double и double /// </summary> /// <param name="par1"></param> /// <param name="par2"></param> void OLoad(double par1, double par2) { Console.WriteLine("double par1 {0}, double par2 {1}",par1, par2); } /// <summary> /// Перегруженный метод OLoad с двумя параметрами типа /// int и float /// </summary> /// <param name="par1"></param> /// <param name="par2"></param> void OLoad(int par1, float par2) { Console.WriteLine("int par1 {0}, float par2 {1}",par1, par2); }



Содержание раздела