首页 > 解决方案 > 计算的只读属性

问题描述

我正在尝试在对象上实现属性,这些属性的值是从其他对象的属性值派生的。例如,名为 Student 的类中名为 TotalPoints 的属性在 get{} 中具有以下代码,

foreach(var subject in Subjects)
{
  _totalPoints += subject.Points;
}

return _totalPoints;

这适用于简单的情况。但是,当涉及更多级别时,例如,Subject.Points 实际上是指其他东西。计算会慢一些。我想弄清楚的是:

欣赏是否有人有任何想法。谢谢。

标签: c#.net-core

解决方案


您所描述的是一个事件驱动的系统(请参阅dot net events)。这是一个简单的例子:

public class PointsProvider
{
    public event Action<int> OnPointsChanged;
    private int points;
    public int Points
    {
        get => points;
        set
        {
            if (points == value)
                return;
            int oldValue = points;
            points = value;
            OnPointsChanged?.Invoke(points - oldValue);
        }
    }
}

public class TotalPointsProvider
{
    private PointsProvider providerA, providerB;

    private int totalPoints;
    public int TotalPoints => totalPoints;

    public TotalPointsProvider()
    {
        providerA = new PointsProvider();
        providerA.OnPointsChanged += UpdateTotalPoints;
        providerB = new PointsProvider();
        providerB.OnPointsChanged += UpdateTotalPoints;

        totalPoints = providerA.Points + providerB.Points;
    }

    private void UpdateTotalPoints(int delta)
    {
        totalPoints += delta;
    }
}

TotalPointsProvider收到通知,一旦它的PointsProvider一个变化和更新它自己的价值。

如果您的子系统 ( PointsProvider) 中有很多更改但不经常请求结果,您可能想要构建一个惰性系统:

public class PointsProvider
{
    public event Action OnPointsChanged;
    private int points;
    public int Points
    {
        get => points;
        set
        {
            if (points == value)
                return;
            points = value;
            OnPointsChanged?.Invoke();
        }
    }
}

public class TotalPointsProvider
{
    private PointsProvider providerA, providerB;

    private bool dirty = true;

    private int totalPoints;
    public int TotalPoints
    {
        get
        {
            if (dirty)
            {
                totalPoints = providerA.Points + providerB.Points;
                dirty = false;
            }
            return totalPoints;
        }
    }

    public TotalPointsProvider()
    {
        providerA = new PointsProvider();
        providerA.OnPointsChanged += RecalculationNecessary;
        providerB = new PointsProvider();
        providerB.OnPointsChanged += RecalculationNecessary;
    }

    private void RecalculationNecessary()
    {
        dirty = true;
    }
}

推荐阅读