Присвоение примитивного типа данных непосредственно пользовательскому объекту с помощью косвенного приведения в C # - PullRequest
0 голосов
/ 10 октября 2018

Я создал класс с именем Parameter, который может содержать общее значение в качестве объекта.С объектом параметра также связан объект Unit, который может предоставить информацию о единице измерения для целей преобразования в других местах моей программы.Что я хочу сделать, так это уметь напрямую назначать классу общие значения типа данных и использовать его для косвенного приведения, чтобы назначить правильный внутренний параметр.Вот упрощенная структура класса в качестве примера:

/// <summary>
/// Class represnting a single parameter, which contains a value and a unit of measure
/// </summary>
public class Parameter
{
    #region Operators

    /// <summary>
    /// Conversion from Parameter to double
    /// </summary>
    static public implicit operator double(Parameter p)
    {
        return Convert.ToDouble(p.BaseValue);
    }

    /// <summary>
    /// Conversion from Parameter to int
    /// </summary>
    static public implicit operator int(Parameter p)
    {
        return Convert.ToInt32(p.BaseValue);
    }

    /// <summary>
    /// Conversion from Parameter to bool
    /// </summary>
    static public implicit operator bool(Parameter p)
    {
        return (bool)p.BaseValue;
    }

    /// <summary>
    /// Conversion from Parameter to DateTime
    /// </summary>
    static public implicit operator DateTime(Parameter p)
    {
        return (DateTime)p.BaseValue;
    }

    /// <summary>
    /// Conversion from Parameter to TimeSpan
    /// </summary>
    static public implicit operator TimeSpan(Parameter p)
    {
        return (TimeSpan)p.BaseValue;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets/Sets the name label for the parameter
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// Gets/Sets the Unit object representing the current unit of measure for the parameter.
    /// </summary>
    public Unit CurrentUnit { get; set; }

    /// <summary>
    /// Gets/Sets the value for the parameter in terms of it's base unit of measure
    /// </summary>
    public object BaseValue { get; set; }

    /// <summary>
    /// Gets/Sets the value for the parameter in terms of it's converted unit of measure (depending on the currentUnit setting)
    /// </summary>
    public object UnitValue
    {
        get
        {
            // Perform unit conversion only if the value is numeric and the CurrentUnit value is not null
            if (!(this.CurrentUnit == null) && (this.BaseValue is double || this.BaseValue is int))
            {
                return Convert.ToDouble(this.BaseValue) * this.CurrentUnit.ConversionFactor;
            }
            else
            {
                return this.BaseValue;
            }
        }

        set
        {
            // Perform unit conversion only if the value is numeric and the CurrentUnit value is not null
            if (!(this.CurrentUnit == null) && (this.BaseValue is double || this.BaseValue is int))
            {
                this.BaseValue = Convert.ToDouble(value) / CurrentUnit.ConversionFactor;
            }
            else
            {
                this.BaseValue = value;
            }
        }
    }

    #endregion
}

Глядя на область кода оператора, в настоящее время у меня есть функции, которые позволяют напрямую присвоить текущему значению объекта параметра значение double, int, bool, DateTime и TimeSpan объекты следующим образом:

Parameter foo;
double aNumber;

// This part works just fine
aNumber = foo;

Но я также хотел бы иметь возможность сделать следующее:

foo = aNumber;

Из того, что я понимаюЯ должен был бы инициализировать новую версию объекта, чтобы присвоить значение aNumber свойству BaseValue, а затем вернуть вновь созданный объект.Проблема в том, что я хочу сохранить все настройки текущего экземпляра и просто обновить свойство и присвоить текущий экземпляр себе (или как-то иначе).Но так как неявное приведение должно быть статическим методом, я не уверен, как получить прямой доступ к значениям экземпляра, чтобы просто внести необходимое изменение в BaseValue и вернуться.Есть ли альтернативный способ обойти это без использования более сложного синтаксиса?Я в основном хочу избежать необходимости:

foo.BaseValue = aNumber;

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

1 Ответ

0 голосов
/ 11 октября 2018

То, что вы хотите сделать, невозможно.

Чтобы понять это, вы должны понимать, что существует два различных типа приведения.

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

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

Что приводит нас к вашему утверждению:

foo = aNumber;

Вы пытаетесь присвоить тип значения к ссылочному типу .

Как вы косвенно поняли, «экземпляра» не существует, поскольку вы конвертируете из типа значения в ссылочный тип.Ваш оператор будет выглядеть примерно так:

static public implicit operator Parameter(double p)
{
    return new Parameter() { BaseValue = p };
}

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

Наконец, поскольку вы хотите сохранить все остальные свойства, вы, по сути, описываете setter , который у вас уже есть:

foo.BaseValue = aNumber;

Просто введите .BaseValue.Вы будете в порядке.

...