使用带有线程安全枚举的 switch case

Posted

技术标签:

【中文标题】使用带有线程安全枚举的 switch case【英文标题】:Using switch case with thread safe enum 【发布时间】:2018-05-02 13:28:46 【问题描述】:

如果我有一个Enum 如下:

private object myEnumValLock = new object();
private MyEnum _myEnumVal;
public MyEnum MyEnumVal

    get
    
        lock(this.myEnumValLock)
        
            return this._myEnumVal;
        
    
    set
    
        lock(this.myEnumValLock)
        
            if (value != this._myEnumVal)
            
                this.HandleNewMyEnumVal(this._myEnumVal, value);
                this._myEnumVal = value;
            
        
    

在使用switch case的时候,可以直接使用这个属性吗:

private void MyFunc()

    switch (this.MyEnumVal)
    
        case MyEnum.First:
            // Do Something
            break;
        case MyEnum.Second:
            // Do Something
            break;
    

或者我应该先阅读它,然后像这样在读取值上使用开关:

private void MyFunc()

    var myEnumVal = this.MyEnumVal;
    switch (myEnumVal)
    
        case MyEnum.First:
            // Do Something
            break;
        case MyEnum.Second:
            // Do Something
            break;
    

如果使用if ... else 和this question 一样,我需要先读取该值。 switch 语句的情况是否相同? switch 语句的行为是什么?它是在每个case 语句中读取值还是在开头只读取一次?

【问题讨论】:

我会直接使用该属性。 (当然,除非我在函数的其他地方也需要它的值,并且它的路径和名称真的很长) @mjwills 在 Windows 7/10 - x64/x86 上运行。正如链接问题中所指出的,对于if ... else,有必要先阅读。 switch 语句的行为是什么?它是在每个case 语句中读取值还是在开头只读取一次? @mjwills 你怎么说?在等价的if .. else 示例中,显示c 在每种情况下都会进行比较。 在你的 getter 中放置一个断点。它被击中多少次?这告诉你什么? 在我到达那里之前,这是一段相对较大的代码。不过,我愿意。 【参考方案1】:

正如@mjwills 建议的那样,我在getter 中放置了一个断点,它只在switch 语句的开头被击中一次。我找不到任何具体的参考资料,它说switch 语句只读取一次值(如果你找到参考资料,请发表评论)。但是断点确实证明了这一点。

因此,虽然在if ... else 的情况下您需要事先读取该值,但在switch 语句的情况下,您不需要。

【讨论】:

以上是关于使用带有线程安全枚举的 switch case的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 - 创建型模式_7种单例模式实现

设计模式 - 创建型模式_7种单例模式实现

设计模式 - 创建型模式_7种单例模式实现

在核心数据线程安全中同时枚举托管对象

深度分析Java的枚举类型—-枚举的线程安全性及序列化问题

Java并发:五种线程安全类型线程安全的实现枚举类型