Свойство C #, возможно ли обойти определение get без определения set (без вспомогательной переменной)? - PullRequest
7 голосов
/ 02 декабря 2009

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

Пример:

public decimal MathValue { get; set; }

Теперь вы решили, что каждое из этих значений должно быть округлено.

Я ищу самый простой способ реорганизовать это без необходимости переписывать все эти свойства.

Что-то из этого эквивалента, которое действительно работает: D:

public decimal MathValue { get {return Math.Round(MathValue);} set; }

Ответы [ 8 ]

6 голосов
/ 02 декабря 2009

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

5 голосов
/ 02 декабря 2009

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

struct RoundedDecimal
{
    public decimal Value { get; private set; }

    public RoundedDecimal(decimal value) : this()
    {
        this.Value = value;
    }

    public static implicit operator decimal(RoundedDecimal d)
    {
        return Math.Round(d.Value);
    }
}

Каждое свойство в вашем классе должно иметь тип RoundedDecimal вместо decimal.

4 голосов
/ 02 декабря 2009

Самый простой способ рефакторинга кода? Вот что я бы сделал:

  1. Откройте Блокнот ++ (получите, если у вас его нет)
  2. Скопируйте / вставьте все свойства класса в пустую текстовую область.
  3. Поместите курсор в начало первой строки: общедоступный десятичный MathValue1 {get; задавать; }
  4. Начать запись макроса (нажмите кнопку записи на панели инструментов)
  5. удерживайте нажатой клавишу Ctrl + стрелка вправо (называемая «слово вправо») 3 раза, чтобы поместить курсор в начало имени свойства.
  6. сделать сдвиг + Ctrl + стрелка вправо 1 раз и сделать копию, чтобы поместить имя свойства в буфер обмена
  7. слово вправо еще 3 раза, чтобы поставить курсор после "get"
  8. удалите точку с запятой после get и начните вводить "{return Math.Round (_"
  9. сделать пасту 10 тип ");}"
  10. слово вправо еще 2 раза, чтобы поставить курсор после «set»
  11. удалить точку с запятой после набора и начать вводить "{_"
  12. сделать пасту
  13. type "= value;}
  14. нажмите клавишу End, чтобы перевести курсор в конец строки
  15. нажмите клавишу со стрелкой вправо, чтобы перевести курсор в начало следующей строки.
  16. нажмите кнопку остановки, чтобы завершить макрос (квадратная кнопка на панели инструментов)
  17. Нажмите кнопку «Запускать макрос несколько раз» (значок с двойной стрелкой на панели инструментов) и произнесите «Выполнить до конца файла»
  18. Скопируйте / вставьте полученный текст обратно в ваш класс, чтобы заменить исходные определения свойств.

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

Я предполагаю, что каждая строка начинается с 2 вкладок и между свойствами нет пустых строк.

Вместо того, чтобы каждое свойство вызывало Math.Round, вы можете рассмотреть возможность определения своей собственной служебной функции, которую они все вызывают, так что если вам нужно изменить ее снова, вы можете просто изменить ее в одном месте.

1 голос
/ 02 декабря 2009

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

public class Base
{
    public virtual decimal MathValue { get; set; }
}

public class Derived : Base
{
    public override decimal MathValue
    {
        get { return Math.Round(base.MathValue); }
    }
}
0 голосов
/ 02 декабря 2009

Вы можете сделать это с помощью PostSharp или какой-либо другой платформы AOP на основе .NET. Вот свойство MethodExecutionEventArgs.ReturnValue , которое говорит, что его можно использовать для «изменения возвращаемого значения ...»

Это сделает это:

[Serializable]
public class RoundingAttribute : OnMethodBoundaryAspect
{
    public override void OnExit(MethodExecutionEventArgs eventArgs)
    {
        base.OnExit(eventArgs);
        eventArgs.ReturnValue = Math.Round((double)eventArgs.ReturnValue, 2);
    }
}

class MyClass
{
    public double NotRounded { get; set; }

    public double Rounded { [Rounding] get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var c = new MyClass
                {
                    Rounded = 1.99999, 
                    NotRounded = 1.99999
                };

        Console.WriteLine("Rounded = {0}", c.Rounded); // Writes 2
        Console.WriteLine("Not Rounded = {0}", c.NotRounded);  // Writes 1.99999
    }
}
0 голосов
/ 02 декабря 2009

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

0 голосов
/ 02 декабря 2009

В Visual Studio был встроенный фрагмент кода "prop", который генерировал бы что-то вроде следующего кода:

    private decimal _MathValue;

    public decimal MathValue
    {
        get { return _MathValue; }
        set { _MathValue = value; }
    }

Это дало бы вам большую часть пути к полному решению, но начиная с VS 2008 теперь оно генерирует автоматическую версию свойства:

    public decimal MathValue { get; set; }

Я еще не пробовал это, но вот предложение для создания собственного фрагмента кода, чтобы получить версию VS 2005 для фрагмента кода "prop" обратно :

0 голосов
/ 02 декабря 2009

Но что произойдет, если клиент не хочет округленное значение? т. е. какой-то новый клиентский код устанавливает десятичное число и ожидает, что это «точное» значение вернется?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...