自从使用.Net 4.0以来,Visual Studio的发布模式中出现InvalidOperationException

Mic*_*cha 18 c# linq enums release .net-4.0

将现有的.NET 3.5应用程序移植到.NET 4.0有些麻烦.该守则不是我自己编写的,所以我不知道为什么事情就像它们一样.

这是情况:如果从Visual Studio启动应用程序(版本或调试模式无关紧要),并且如果应用程序从Debug-folder启动,则代码工作正常问题是Release-deploy,因为它不是'自4.0(以及4.5)以来运作良好: - /

这是最初的电话:

someObject.Text = Elements.GetElement(Int16.Parse(cb1.Text));
Run Code Online (Sandbox Code Playgroud)

这是代码:

public class Elements : EnumBase<int, Elements>
{
    public static readonly Elements Element1 = Create("Number 0", 0);
    public static readonly Elements Element2 = Create("Number 1", 1);

    private static Elements Create(string text, int value) 
    {
        return new Elements() { text = text, value = value };
    }

    public static String GetElement(int id)
    {

        // The Following Code safes the day and let the release deploy work fine.
        // It doesn´t matter if the condition becomes true or not to runtime.
        /* 
        if (id == 999999999)
        {
            Elements el = Element1;
        }
        */

        // Release deploy works also fine if you do the following line in a loop instead of linq.
        return BaseItemList.Single(v => v.Value == id).Text; 
    }
}

[Serializable()]
public class EnumBase<T, E> :  IEqualityComparer<E> 
        where E : EnumBase<T, E>
{
    private static readonly List<E> list = new List<E>();
    protected string text;
    protected T value;

    protected static IList<E> BaseItemList
    {
        get
        {
            return list.Distinct(new EnumBase<T, E>(false)).ToList();
        }
    }

    protected EnumBase()
    {
        list.Add(this as E);
    }

    /// <summary>
    /// Constructor for distinct to avoid empty elements in the list
    /// </summary>   
    private EnumBase(bool egal) {}

    public string Text
    {
        get { return text; }
    }

    public T Value
    {
        get { return value; }
    }


    #region IEqualityComparer<E> Member

    // ...

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

关键是return BaseItemList.Single(v => v.Value == id).Text;.它抛出一个InvalidOperationException,因为在Release中 public static readonly Elements Element1 = Create("Number 0", 0);public static readonly Elements Element2 = Create("Number 1", 1);没有准备好.在异常时刻,BaseItemList为空(BaseItemList.Count = 0).我不知道为什么这发生在发布形式的bin-folder中,而不是发布在visual studio中.对于测试,我在项目属性中停用了"优化代码",但它没有帮助.

当然,构造不是最好的,但我想知道.Net 4.0中的不同之处使代码变得更加平坦.

感谢帮助

Jon*_*eet 21

我相信问题是你依赖静态初始化程序来Elements运行,尽管事实上你没有引用其中的任何字段.没有静态构造函数的类型中的类型初始化程序仅保证在第一次静态字段访问之前运行.C#5规范的第10.5.5.1节:

如果类中存在静态构造函数(第10.12节),则在执行该静态构造函数之前立即执行静态字段初始值设定项.否则,静态字段初始化器在第一次使用该类的静态字段之前的实现相关时间执行.

第10.12节有:

封闭类类型的静态构造函数在给定的应用程序域中最多执行一次.静态构造函数的执行由应用程序域中发生的以下第一个事件触发:

  • 创建类类型的实例.
  • 引用类类型的任何静态成员.

类型初始化的实现在.NET 4中已更改,但它只是一个实现细节 - 您的代码之前已被破坏,您只是不知道它.

如果您将代码更改为:

static Elements() {}
Run Code Online (Sandbox Code Playgroud)

Elements类,那么我相信它会工作-因为之前立即最先发生静态构造函数力型初始化成员访问,而不是仅仅"第一次之前的一些点现场访问".

就个人而言,我对一般模式持怀疑态度,但这是一个略有不同的问题.