C#属性,是否可以在没有定义set(没有后备变量)的情况下定义get?

时间:2009-12-01 23:06:11

标签: c# properties

假设您有一个具有300个属性而没有支持变量的类,每个属性都返回一个十进制/双精度。

示例:

public decimal MathValue { get; set; }

现在你决定将每个值都舍入。

我正在寻找最简单的重构方法,而不必重写所有这些属性。

实际上有效的东西:D:

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

8 个答案:

答案 0 :(得分:6)

没有。如果在getter或setter中需要任何自定义逻辑,则不能使用自动属性。

答案 1 :(得分:5)

您可以创建一个假装为小数的新值类型,但返回舍入值。像这样:

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

答案 2 :(得分:4)

重构代码的最简单方法?这就是我要做的事情:

  1. 打开Notepad ++(如果你没有它,就去拿它)
  2. 将班级的所有属性复制/粘贴到空白文本区域。
  3. 将光标放在第一行的开头:     公共十进制MathValue1 {get;组; }
  4. 开始录制宏(单击工具栏上的录制按钮)
  5. 按住ctrl +向右箭头(称为“单词右侧”)3次,将光标放在属性名称的开头。
  6. 执行shift + ctrl +右箭头1次并执行复制以将属性的名称放在剪贴板中
  7. 字右3次将光标放在“get”
  8. 之后
  9. 在get之后删除分号并开始输入“{return Math.Round(_”
  10. 做一个粘贴 10类型“);}”
  11. 单词右2次将光标放在“set”
  12. 之后
  13. 在集合后删除分号并开始输入“{_”
  14. 做一个粘贴
  15. type“= value;}
  16. 按End键将光标移至行尾
  17. 按右箭头键将光标移至下一行的开头。
  18. 按停止按钮结束宏(工具栏上的方形按钮)
  19. 单击“多次运行宏”按钮(工具栏上的双箭头图标)并说“运行直到文件末尾”
  20. 将生成的文本复制/粘贴回您的班级,以替换原始属性定义。
  21. 现在,您需要定义一组对应的私有变量,这些变量以下划线开头,但与属性具有相同的名称。从您班级的新属性副本开始,然后按照上述步骤执行类似的步骤。

    我的假设是每行以2个制表符开头,属性之间没有空行。

    您可能需要考虑定义自己调用的自己的实用程序函数,而不是让每个属性调用Math.Round,这样如果您需要再次更改它,您可以在一个地方更改它。

答案 3 :(得分:1)

您可以创建此类的派生,以覆盖gets并返回舍入值。然后,您需要将基本属性修改为虚拟。但这样就可以在不定义集合和使用自动属性的情况下定义get。

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

public class Derived : Base
{
    public override decimal MathValue
    {
        get { return Math.Round(base.MathValue); }
    }
}

答案 4 :(得分:0)

但是如果客户端不想要舍入值会发生什么?即,一些新的客户端代码设置一个小数,并期望“准确”值回来?

如果某些客户端确实需要对属性调用的输出进行舍入,那么客户端应该处理此问题并让您的课程独自完成。

答案 5 :(得分:0)

Visual Studio曾经有一个内置的“prop”代码片段,可以生成如下代码:

    private decimal _MathValue;

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

这将使您获得完整解决方案的大部分,但自VS 2008以来它现在生成自动属性版本:

    public decimal MathValue { get; set; }

我还没有尝试过,但是here is a suggestion for creating your own code snippet to get the VS 2005 version of the "prop" code snippet back

答案 6 :(得分:0)

一种选择是使用面向方面的编程在返回时拦截属性调用,并在将控制权传递给调用者之前舍入返回值。

答案 7 :(得分:0)

您可以使用PostSharp或其他一些基于.NET的AOP框架执行此操作。这是MethodExecutionEventArgs.ReturnValue property,表示它可以用来“修改返回值...”

这样做:

[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
    }
}