Пусть два класса со следующей неявной и явной шаблон оператора:О разрешении перегрузки оператора
class Foo
{
public static implicit operator decimal (Foo foo)
{
throw new NotImplementedException();
}
public static implicit operator Foo (decimal value)
{
throw new NotImplementedException();
}
public static Foo operator +(Foo left, Foo right)
{
throw new NotImplementedException();
}
}
class Bar
{
public static explicit operator decimal (Bar bar)
{
throw new NotImplementedException();
}
public static explicit operator Foo(Bar bar)
{
throw new NotImplementedException();
}
}
Теперь рассмотрим следующий код:
var foo = new Foo();
var bar = new Bar();
var resultFooAddBar = foo + (decimal)bar;
неявно типизированным resutlFooAddBar
решает Foo
и оператор добавления разрешается до Foo Foo.operator +
. Почему этот код не дает неоднозначной ошибки? Оператор мог бы в равной степени разрешить decimal decimal.operator +
. Это потому, что пользовательские операторы: всегда считается лучшим вариантом? Тем не менее, выбор кажется немного странным, учитывая, что Bar
имеет явное приведение Foo
, который не был использован, который будет явно определить какой оператор программист хотел бы использовать:
var resultFooAddBar = foo + (Foo)bar;
// OK, я явно говорю Я хочу Foo Foo.operator +
Если вместо decimal
мы используем третий класс Tango
, определяющие Tango Tango.operator + (Tango, Tango)
и тот же скрытые и явные модели оператора тогда Неоднозначная ошибка вызова, брошенный компилятор.
Почему это различие между определенными пользователем операторами и не определенными пользователем операторами?
UPDATE: Я создал отдельный узел, включающий в следующий класс, чтобы опробовать exlanation Servy в:
namespace ExternalAssembly
{
public class Tango
{
public static Tango operator +(Tango left, Tango right)
{
throw new NotImplementedException();
}
}
}
, а затем изменили decimal
к Tango
в Foo
и Bar
и добавив необходимую ссылку на ExternalAssembly длл. В этом случае я все еще получаю «+» оператор неоднозначен в операндах «ConsoleApplication.Foo» и «ExternalAssembly.Tango». Почему бы не компилятор, в этом случае, выбрать ту же самую перегрузку Foo Foo.operator +
, что и в моем исходном вопросе с decimal
?
@Servy 'decimal' +' decimal'. Существует неявное преобразование из 'Foo' в' decimal', но вместо этого компилятор выбирает неявное преобразование из 'decimal' в' Foo'. См. Последний абзац (только что измененный). – InBetween