Ошибка C #: вызов неоднозначен между следующими методами или свойствами. Перегрузка операторов

#c# #.net #compiler-construction #operators #operator-overloading

#c# #.net #компилятор-конструкция #операторы #оператор-перегрузка

Вопрос:

У меня есть 2 класса с перегруженными операторами в пространстве имен с именем Dinero, это 2 класса:

Первый:

 namespace Dinero
{
    class Dollar
    {
        #region Atributos

        public Double cant;

        #endregion

        #region Constructores

        public Dollar()
        {
            this.cant = 0;
        }

        public Dollar(Double amount)
        {
            this.cant = amount;
        }

        #endregion

        #region Sobrecarga de Operadores

        public static Dollar operator  (Euro eu, Dollar dol)
        {
            Dollar devolucion = new Dollar();

            devolucion.cant = eu.cant   (dol.cant * 1.3642);

            return devolucion;
        }

        public static Dollar operator -(Euro eu, Dollar dol)
        {
            Dollar devolucion = new Dollar();

            devolucion.cant = eu.cant   (dol.cant * 1.3642);

            return devolucion;
        }

        public static bool operator ==(Euro eu, Dollar dol)
        {
            if (eu.cant == (dol.cant * 1.3642))
                return true;
            else
                return false;
        }

        public static bool operator !=(Euro eu, Dollar dol)
        {
            if (eu.cant != (dol.cant * 1.3642))
                return true;
            else
                return false;
        }

        #endregion

    }
}
  

Второй:

 namespace Dinero
{
    class Euro
    {
        #region Atributos

        public Double cant;

        #endregion

        #region Constructores

        public Euro()
        {
            this.cant = 0;
        }

        public Euro(Double amount)
        {
            this.cant = amount;
        }

        #endregion

        #region Sobrecarga de operadores

        public static Euro operator  (Euro eu, Dollar dol)
        {
            Euro devolucion = new Euro();

            devolucion.cant = eu.cant   (dol.cant * 1.3642);

            return devolucion;
        }

        public static Euro operator -(Euro eu, Dollar dol)
        {
            Euro devolucion = new Euro();

            devolucion.cant = eu.cant - (dol.cant * 1.3642);

            return devolucion;
        }

        public static bool operator ==(Euro eu, Dollar dol)
        {
            if (eu.cant == (dol.cant * 1.3642))
                return true;
            else
                return false;
        }

        public static bool operator !=(Euro eu, Dollar dol)
        {
            if (eu.cant != (dol.cant * 1.3642))
                return true;
            else
                return false;
        }

        #endregion

    }
}
  

И когда я перехожу к основной программе (я не знаю, как вы, ребята, вызываете основной файл, я хотел бы знать, поскольку я всего лишь n00b), и я набираю это:

 namespace Ejercicio_21
{
    class Ejercicio_21
    {
        static void Main(string[] args)
        {
            Console.Title = "Ejercicio Nro 21";

            Euro euro00 = new Euro(1);
            Dollar dollar00 = new Dollar(1);

            Euro sumaEuros = euro00   dollar00;
  

О последней строке компилятор говорит:

Ошибка 11 Вызов неоднозначен между следующими методами или свойствами: ‘Dinero.Euro.operator (Dinero.Euro, Dinero.Доллар)’ и ‘Dinero.Dollar.operator (Dinero.Euro, Dinero.Доллар) ‘

Я предполагаю, что это как-то связано с разными пространствами имен, но я не мог понять это, даже используя Google.

Это первый вопрос, который я задаю здесь, поэтому, пожалуйста, не доводите меня до забвения и, пожалуйста, извините за мой ужасный английский.

Примечание: я вынужден хранить классы Dollar и Euro в пространстве имен, отличном от основной программы.

Заранее благодарю вас.

Комментарии:

1. Не связано: пользователь не Double должен указывать сумму в валюте. double и float , с другой стороны, они больше подходят для научных вычислений (где «довольно близко» достаточно хорошо.) decimal , С другой стороны, гарантирует, что ваши финансовые вычисления поддерживают необходимую вам десятичную точность.

2. Вы также можете получить эту ошибку, если хотите начать с какого-то уже существующего кода (уйти во что-то) и не дать скопированному классу новое имя.

Ответ №1:

Нет, это не имеет никакого отношения к разным пространствам имен — просто у вас одна и та же сигнатура оператора, объявленная в двух местах:

 public static Dollar operator  (Euro eu, Dollar dol)
public static Euro operator  (Euro eu, Dollar dol)
  

Компилятор не знает, какой из них вы хотите вызвать.

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

Если вы действительно хотите, чтобы две операции были действительными, я бы предложил вызвать методы экземпляра Plus :

 // In Dollar
public Dollar Plus(Euro eu)

// In Euro
public Dollar Plus(Dollar dol)
  

Затем:

 Euro euro00 = new Euro(1);
Dollar dollar00 = new Dollar(1);

Euro sumaEuros = euro00.Plus(dollar00);
  

Почти так же ясно, но без двусмысленности.

Другая альтернатива, которую я не рекомендую, — сделать (скажем), чтобы тип первого операнда имел приоритет:

 public static Dollar operator  (Dollar dol, Euro eu)    
public static Euro operator  (Euro eu, Dollar dol)
  

Тогда вы могли бы сделать:

 Dollar dol1 = ...;
Euro eu1 = ...;

Dollar dol2 = dol1   eu1;
Euro eu2 = eu1   do1;
  

Хотя это довольно ужасно.

Комментарии:

1. Прежде всего, спасибо. Должен ли я выбирать один из двух классов для размещения перегрузок операторов?

2. @Cristian: вы можете поместить операторы в оба класса, но нет смысла иметь два оператора с одинаковой сигнатурой .

3. Спасибо, но мой учитель заставляет нас перегружать операторы таким образом. Ваш метод явно лучше, но мне придется придерживаться перегрузки операторов.

4. @Cristian: Тогда вам нужно будет присвоить им разные подписи. Все еще плохая идея даже иметь операции добавления для этих типов, IMO…

5. Неплохо… Я попробую этот ужасный метод … моему учителю понравится что-то подобное, хахаха

Ответ №2:

Это связано с тем, что вы объявили

 public static Your_Type operator  (Euro eu, Dollar dol)
  

в обоих классах.
Поэтому ваш компилятор не знает, какой из них использовать…

Комментарии:

1. Прежде всего, спасибо. Должен ли я выбирать один из двух классов для размещения перегрузок операторов?

2. @Cristian: Джон Скит уже дал вам лучший ответ (как обычно) 🙂

Ответ №3:

Решена эта проблема в VS 2015 путем удаления дублированного кода, который был как в проекте, так и в пакете NuGet. При выгрузке проекта, в котором был дублированный код, ошибка исчезла.