是的,这正是我想做的:)至少对于特定的课程。 问题是,我创建了一个对象的静态实例,但我不直接使用它。由于我在构造函数中执行了一些操作,例如将对象添加到列表中,因此在获取列表之前必须至少调用构造函数一次。
我猜编译器只是优化了未使用的对象。
必须有一个简单的解决方案:-/
编辑
好吧,也许我错过了什么。让我发布我的代码。我为自定义枚举目的编写了一个类。
public class TypeSafeEnum<TNameType, TValueType>
{
protected readonly TNameType name;
protected readonly TValueType value;
private static List<TypeSafeEnum<TNameType, TValueType>> listEnums = new List<TypeSafeEnum<TNameType, TValueType>>();
protected TypeSafeEnum(TNameType name, TValueType value)
{
this.name = name;
this.value = value;
listEnums.Add(this);
}
public TNameType Name
{
get { return name; }
}
public TValueType Value
{
get { return value; }
}
public static TypeSafeEnum<TNameType, TValueType> GetName(TNameType name)
{
TypeSafeEnum<TNameType, TValueType> tse = null;
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
if (EqualityComparer<TNameType>.Default.Equals(typeSafeEnum.name, name))
{
tse = typeSafeEnum;
}
}
return tse;
}
public static TypeSafeEnum<TNameType, TValueType> GetValue(TValueType value)
{
TypeSafeEnum<TNameType, TValueType> tse = null;
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
if (EqualityComparer<TValueType>.Default.Equals(typeSafeEnum.value, value))
{
tse = typeSafeEnum;
}
}
return tse;
}
public static TNameType[] GetNames()
{
TNameType[] names = new TNameType[listEnums.Count];
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
names[i] = typeSafeEnum.name;
}
return names;
}
public static TValueType[] GetValues()
{
TValueType[] values = new TValueType[listEnums.Count];
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
values[i] = typeSafeEnum.value;
}
return values;
}
}
public abstract class StringEnum : TypeSafeEnum<string, int>
{
protected StringEnum(string name, int value) : base(name, value)
{
}
}
public sealed class FileOptionEnum : StringEnum
{
public static readonly FileOptionEnum Name = new FileOptionEnum("Name", 0);
public static readonly FileOptionEnum Extension = new FileOptionEnum("Extension", 1);
public static readonly FileOptionEnum Size = new FileOptionEnum("Size", 2);
public static readonly FileOptionEnum LastModified = new FileOptionEnum("Last Modified", 3);
public static readonly FileOptionEnum LastOpened = new FileOptionEnum("Last Opened", 4);
public static readonly FileOptionEnum Created = new FileOptionEnum("Created", 5);
public FileOptionEnum(string name, int value) : base(name, value)
{
}
}
这是我的使用方法:
// if I omit this line it returns me empty array
FileOptionEnum @enum = FileOptionEnum.Name;
string[] names = FileOptionEnum.GetNames();
cbFileOptions.Items.AddRange(names);
你可以简单地写
new YourObject();
这不会被优化掉。
但是,除非类的构造函数将自身保存在某个地方(例如,将对象添加到列表或静态字段,或者将事件处理程序添加到其他内容),否则该对象可能会立即被垃圾收集。
首先,请验证编译器是否确实优化了代码。很可能,事实并非如此:如果您的构造函数调用有副作用,编译器实际上无权消除它。
如果它确实得到了优化,您可以使用
GC.KeepAlive
方法来保证对象仍然存在:
GC.KeepAlive( new MyObj() );
这个方法实际上并没有做任何事情——它的主体是空的。但它的特殊之处在于它无法被优化。所以如果你用一些参数来调用它,那么该参数也无法被优化掉。
你的想法行不通。
静态
List<TypeSafeEnum<TNameType, TValueType>> listEnums
字段将由具有相同名称和值类型的所有 TypeSafeEnum
类共享。
要解决该问题,请为实际枚举类添加一个参数,如下所示:
public class TypeSafeEnum<TEnum, TName, TValue> where TEnum : TypeSafeEnum<TEnum, TName, TValue>
(然后您可以将所有
TypeSafeEnum<...>
字段和参数替换为 TEnum
)
我很确定这也能解决您的实际问题。
由于基类
TypeSafeEnum
现在引用继承的枚举类,继承类的静态构造函数将运行,初始化值。
如果您只是使用一些静态功能,为什么还要使用实例呢? 创建一个静态类,并有一个静态“Initialize()”方法,您可以调用该方法来设置对象。
静态成员在您尝试显式访问它们之前不保证被初始化。 您可以通过创建显式静态构造函数(以避免 beforeFieldInit 行为)并显式访问静态方法(如虚拟 Init 方法)来强制静态初始化来解决此问题。