Неявное приведение типов в C#
Возникли проблемы с пониманием приведения типов в C#. Я создал простой класс и перегрузил для него метод ToString(),чтобы выводились в строчку значения полей объекта класса:
public class Triple
{
public int Int32;
public string String;
public bool Boolean;
public Triple(int Int32, string String, bool Boolean)
{
this.Int32 = Int32;
this.String = String;
this.Boolean = Boolean;
}
public override string ToString()
{
return String.Format("{0},{1},{2}", this.Int32, this.String, this.Boolean);
}
Также я задал неявное приведения объекта класса Triple к типу bool:
public static implicit operator bool(Triple T1)
{
return T1.Boolean;
}
Теперь при вызове
Triple t1 = new Triple(1, "abcd", true);
Console.WriteLine(t1);
Выводится поле Boolean класса Triple,а не значение полей класса.Почему так происходит?Заранее спасибо за ответы!
Ответы (1 шт):
В данном случае у вас есть 2 конкурирующих перегрузки метода Console.WriteLine:
WriteLine(bool)— принимаетboolWriteLine(object)— принимаетobject
Ваш тип, а точнее, объект вашего типа, подходит под обе перегрузки:
implicit operator bool(Triple)— подходит под 1-ю перегрузку- Неявное наследование от
object— подходит под 2-ю перегрузку
И что же выберет вам компилятор? В .NET действует 1 простое правило: «больше извращённость — больше приоритет».
В данном случае "извращённость" больше у неявного оператора upcast'а к bool, чем у наследования, т.к. bool > object.
Такая расстановка приоритетов связанна ещё с такими случаями:
public struct MyBoolean : IMyInterface
{
readonly bool value;
// реализация своего `bool`
}
Такой тип нужен только в 1-м случае: если вам нужен bool, реализующий какой-либо интерфейс, при этом это именно bool, а не объект с состоянием bool. Т.е. в MyBoolean перегрузка операторов и создание соответствующих true/false констант нужны, т.к. MyBoolean — это именно bool, но с интерфейсом. А вот уже условный ManualResetEvent — это другое; в нём единственное, фактически, состояние — 1 поле типа bool, но никто в нём не делает мер, которые были бы сделаны типу MyBoolean, т.к.
Вы не понимаете — это другое!
И как вы думаете, что ожидает человек от такого кода:
var @bool = new MyBoolean(true);
Console.WriteLine(@bool);
Конечно же True в консоль, а не имя типа MyBoolean со всеми пространствами имён.