我将现有的.NET 3.5应用程序移植到.NET 4.0时遇到了一些麻烦。代码不是我自己写的,所以我不知道为什么这些东西是这样的。
这是情况:如果应用程序是从Visual Studio启动的(发布或调试模式无关紧要),并且应用程序是从调试文件夹启动的,则代码工作正常问题是发布部署,因为自 4.0(以及 4.5)以来效果不佳:-/
这是初始调用:
someObject.Text = Elements.GetElement(Int16.Parse(cb1.Text));
这是代码:
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
}
关键是return BaseItemList.Single(v => v.Value == id).Text;
.它抛出了一个InvalidOperationException
,因为在发布中 public static readonly Elements Element1 = Create("Number 0", 0);
和public static readonly Elements Element2 = Create("Number 1", 1);
还没有准备好。在异常的时刻,BaseItemList 为空 (BaseItemList.Count = 0)。我不确定为什么这发生在发布表单 bin-文件夹中,而不是在视觉工作室之外的版本中。对于测试,我在项目属性中停用了"优化代码",但它没有帮助。
当然,构造不是最好的,但我想知道 .Net 4.0 有什么不同,使代码更扁平。
感谢您的帮助
我相信问题在于您依赖于静态初始值设定项来运行Elements
,尽管您没有引用其中的任何字段。没有静态构造函数的类型中的类型初始值设定项仅保证在第一次静态字段访问之前运行。C# 5 规范的第 10.5.5.1 节:
如果类中存在静态构造函数 (§10.12),则在执行该静态构造函数之前立即执行静态字段初始值设定项。否则,静态字段初始值设定项将在首次使用该类的静态字段之前在与实现相关的时间执行。
第10.12节有:
封闭类类型的静态构造函数在给定的应用程序域中最多执行一次。静态构造函数的执行由应用程序域中发生的以下第一个事件触发:
- 将创建类类型的实例。
- 引用类类型的任何静态成员。
类型初始化的实现在 .NET 4 中发生了变化,但这只是一个实现细节 - 你的代码以前被破坏了,你只是不知道它。
如果将代码更改为具有:
static Elements() {}
在 Elements
类中,那么我相信它会起作用 - 因为静态构造函数强制类型初始化在第一个成员访问之前立即发生,而不仅仅是"在第一个字段访问之前的某个时间点"。
就个人而言,我对一般模式持怀疑态度,但这是一个略有不同的问题。