简体   繁体   English

计算出的只读属性

[英]Calculated read-only properties

I am trying to implement properties on objects which values are derived from values of properties from other objects.我正在尝试在对象上实现属性,这些属性的值源自其他对象的属性值。 For example, a property named TotalPoints in a class named Student has the following code in get{},例如,名为 Student 的类中名为 TotalPoints 的属性在 get{} 中有以下代码,

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

return _totalPoints;

This works for simple case.这适用于简单的情况。 However, when there are more levels involved, eg, Subject.Points is actually refers to something else.然而,当涉及到更多层次时,例如,Subject.Points 实际上是指别的东西。 The calculation will be slower.计算会比较慢。 What I am trying to figure out is the following:我想弄清楚的是:

  • If there is any way to detect if there is any changes in value in Points, if not, I do not want to recalculate _totalPoints;如果有什么方法可以检测Points的值是否有变化,如果没有,我不想重新计算_totalPoints;

  • Is there any alternative way to implement this?有没有其他方法可以实现这一点? What I am thinking is also if it is possible to "inform" TotalPoints that one of the Subject.Points' value has changed, so TotalPoints needs to be re-calculated.我在想的是,是否有可能“通知” TotalPoints Subject.Points 的值之一已更改,因此需要重新计算 TotalPoints。

Appreciate if anyone has any idea.如果有人有任何想法,不胜感激。 Thanks.谢谢。

What you describe is an event driven system (see dot net events ).您所描述的是一个事件驱动系统(请参阅dot net events )。 Here's a simple example:这是一个简单的例子:

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 gets notified, once one of it's PointsProvider s changes and updates it's own value. TotalPointsProvider收到通知,一旦它的PointsProvider更改并更新它自己的值。

If you have lot's of changes in your sub system ( PointsProvider ) but request the result unfrequently you might want to build a lazy system:如果您的子系统 ( 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;
    }
}
get
    {
        return _totalPoints;
    }
set
    {
        foreach(var subject in Subjects)
         {
        _totalPoints += subject.Points;
         }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM