【问题标题】:Turn a variable into constant将变量变为常量
【发布时间】:2014-03-19 12:28:29
【问题描述】:

是否存在任何 C# 类型/结构可以使变量变成常量? 也许通过设置一个固定值的标志。

示例代码:

foreach (Person p in group)
{
    if (p.Mood.Equals("bad"))
    {
        group.Mood = "bad";
        group.Mood.Fix(); // This should disable any further changing on group.Mood 
    }
    else
    {
        group.Mood = "good";
    }
}

如果一个人心情不好,整个团队的心情都应该是“坏”的。 我知道我可以自己实现这样的东西,但我经常使用它,我可以想象这样的结构已经存在。

希望大家心情愉快! ;)

【问题讨论】:

  • 没有为此内置任何东西。这种模式有时被称为“冰棒”或“冰棒不变性”(即你在某个时候冻结它)。另外,我建议不要拥有一个您可以设置但忽略新值的属性,如果一个人心情不好,而下一个人心情好,就会发生这种情况。我会在那个时候跳出循环并忽略整个 const/immutability 问题。
  • 谢谢,还有个问题:为什么叫“冰棒”?
  • 好吧,这是因为它在“使用”之前首先是液体并且大部分是冷冻的? ;)
  • 没错,它有液态(可变)状态和冻结(不可变)状态。

标签: c# variables constants


【解决方案1】:

不,变量在声明时保持不变。但是,您可以使用属性设置器获得一些接近的结果:

public string Mood
{
    set 
    {
       if(mood != "Bad")
            mood = value; 
    }
}

【讨论】:

    【解决方案2】:

    出于以下原因,我建议不要这样做:

    1. 应该允许设置带有 setter 的属性
    2. 具有 setter 的属性不应简单地忽略赋予它的值

    其次,既然已经确定了最终价值,为什么还要看更多的人收藏?

    我会将代码改为以下三种变体之一:

    group.Mood = "good";
    foreach (Person p in group)
    {
        if (p.Mood.Equals("bad"))
        {
            group.Mood = "bad";
            break;
        }
    }
    

    或者这个:

    string groupMood = "good";
    foreach (Person p in group)
    {
        if (p.Mood.Equals("bad"))
        {
            groupMood = "bad";
            break;
        }
    }
    group.Mood = groupMood;
    

    或者这个:

    if (group.Any(p => p.Mood == "bad"))
        group.Mood = "bad";
    else
        group.Mood = "good";
    

    如果您想要这样一种“冰棒”类型,您可以尝试使用LINQPad

    void Main()
    {
        var i = new Popsicle<int>(10);
        i.Value = 25;
        i.Value = 33;
        i.Dump();
    
        i.Freeze(FrozenBehavior.IgnoreNewValues);
        i.Value = 17;
        i.Dump();
    
        i = new Popsicle<int>(10);
        i.Freeze(FrozenBehavior.ThrowException);
        i.Value = 17;
        i.Dump();
    }
    
    public class Popsicle<T>
    {
        private T _Value;
        private FrozenBehavior? _FrozenBehavior;
    
        public Popsicle(T value = default(T))
        {
            _Value = value;
        }
    
        public T Value
        {
            get
            {
                return _Value;
            }
    
            set
            {
                if (_FrozenBehavior.HasValue)
                {
                    switch (_FrozenBehavior.GetValueOrDefault())
                    {
                        case FrozenBehavior.IgnoreNewValues:
                            break;
    
                        case FrozenBehavior.ThrowException:
                            throw new InvalidOperationException("This Popsicle<T> has been frozen and configured to throw exceptions if an attempt is made to change its value");
    
                        default:
                            throw new InvalidOperationException("This Popsicle<T> is in an invalid frozen state");
                    }
                }
                else
                    _Value = value;
            }
        }
    
        public void Freeze(FrozenBehavior behavior = FrozenBehavior.ThrowException)
        {
            if (!_FrozenBehavior.HasValue)
                _FrozenBehavior = behavior;
            else
                throw new InvalidOperationException("This Popsicle<T> has already been frozen, cannot re-freeze");
        }
    
        public override string ToString()
        {
            if (!_FrozenBehavior.HasValue)
                return _Value + " (unfrozen)";
            else switch (_FrozenBehavior)
            {
                case FrozenBehavior.IgnoreNewValues:
                    return _Value + " (frozen: ignore)";
    
                case FrozenBehavior.ThrowException:
                    return _Value + " (frozen: throw)";
    
                default:
                    throw new InvalidOperationException("This Popsicle<T> is in an invalid frozen state");
            }
        }
    }
    
    public enum FrozenBehavior
    {
        IgnoreNewValues,
        ThrowException
    }
    

    【讨论】:

    • 我像你解释的那样解决了它,感觉就像一千次。因此我问这种情况是否有特殊的“类型”。不管怎么说,还是要谢谢你! :)
    • 好的,如果没有内置结构,我将自己实现“冰棒”类型。谢谢你的榜样!还有一个问题:为什么叫“冰棒”?
    【解决方案3】:

    使用 LinQ,这可以在很短的时间内完成。检查是否有任何人心情不好,如果有,请将 group-mood 设置为bad,否则设置为good

    group.Mood = group.Any(p => p.Mood == "bad") ? "bad" : "good";
    

    【讨论】:

      猜你喜欢
      • 2014-11-14
      • 2021-11-01
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多