如何计算 C# 中对象内所有属性的总数?

How to calculate total of all properties within the object in C#?

public class Calories
{
  public decimal A { get; set; }
  public decimal B { get; set; }
  public decimal C { get; set; }
  public decimal Total { get; set; }
}

var calories = new Calories
{ 
  A = 10, B = 25, C = 31
};

//Currently I am doing this
calories.Total = calories.A + calories.B + calories.C;

计算同一对象中所有属性总数的有效方法是什么?

是的。你可以计算属性里面的总和 getter:

public decimal Total { get { return A + B + C } };

我要做的是创建一个 CaloriesList 并且在你的 class 中你可以有一个 Property Total 在你的列表中调用 Sum

像这样:

public class Calories
{
  public List<decimal> Calories;
  public decimal Total{ get { return this.Calories.Sum(); } }

  public Calories()
  {
    this.Calories = new List<decimal>();
  }
}

并没有真正回答您的问题,但是如果您愿意接受不同的设计,并且您想要一个 class 具有未确定的值的总数 属性..

class Calories : List<decimal>
{
    public decimal Total { get { return this.Sum(); } }
}

可能不是最好的方法.. 取决于具体情况,但速度快且代码最少。

虽然这比简单地手动将小数加在一起要慢得多,而且有点死板,因为您明确排除了字符串的总计 属性,但以下反射将仅对您的 Decimal 列求和而不会中断遇到不是小数的属性。

public class Calories
{
    public decimal A { get; set; }
    public decimal B { get; set; }
    public decimal C { get; set; }
    public string TestString { get;set;}

    public decimal Total 
    { 
        get
        {
            return typeof(Calories)
                .GetProperties()
                .Where (x => x.PropertyType == typeof(decimal) 
                    && x.Name != "Total")
                .Sum(p => (decimal)p.GetValue(this));
        }
    }
}

请记住,更好的 class 结构或 Yuval 的答案会更可取,因为它可以适当地保持强类型和性能。为了完整性,我将其添加为 "pure reflection" 答案。

最后,如果您想使用反射来动态访问未知数量的十进制属性,但又想避免大量的反射成本,您可以使用像 FastMember 这样的库来减轻性能影响。

public class Calories
{
    public decimal A { get; set; }
    public decimal B { get; set; }
    public decimal C { get; set; }
    public string TestString { get;set;}

    public decimal Total 
    { 
        get
        {
            var accessor = FastMember.TypeAccessor.Create(this.GetType());

            return accessor.GetMembers()
                .Where (x => x.Type == typeof(decimal) && x.Name != "Total")
                .Sum(p => (decimal)accessor[this, p.Name]);
        }
    }
}