强制 C# 编译器创建未使用的对象实例
是的,这正是我想做的:)至少对于特定的课程。 问题是,我创建了一个对象的静态实例,但我不直接使用它。由于我在构造函数中执行了一些操作,例如将对象添加到列表中,因此在获取列表之前必须至少调用构造函数一次。
我猜编译器只是优化了未使用的对象。
必须有一个简单的解决方案:-/
编辑
好吧,可能我错过了一些东西。让我发布我的代码。我为自定义枚举目的编写了一个类。
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你可以简单地写
这不会被优化掉。
然而,除非类的构造函数将自身保存在某个地方(例如,将对象添加到列表或静态字段,或者将事件处理程序添加到其他内容),否则该对象可能会立即被垃圾收集。
You can simply write
This will not be optimized away.
However, unless the class's constructor saves itself somewhere (eg, adding the object to list or static field, or adding an event handler to something else), the object will probably be garbage-collected right away.
首先,请验证编译器确实优化了代码。很可能,事实并非如此:如果您的构造函数调用有副作用,编译器实际上无权消除它。
如果它确实得到了优化,您可以使用 GC.KeepAlive 方法来保证对象保留:
此方法实际上不执行任何操作 - 它具有空主体。但它的特殊之处在于它无法被优化。所以如果你用一些参数来调用它,那么这个参数也不能被优化掉。
First of all, please verify that the compiler indeed does optimize the code away. Chances are, it really doesn't: if your constructor call has side effects, the compiler doesn't really have the right to get rid of it.
And if it actually does get optimized away, you can use the
GC.KeepAlive
method to guarantee that the object remains:This method doesn't really do anything - it has empty body. But it's special in a way that it can't be optimized out. So it you call it with some argument, then that argument also can't be optimized out.
你的想法行不通。
静态
List> listEnums
字段将由具有相同名称和值类型的所有TypeSafeEnum
类共享。要解决该问题,请为实际枚举类添加一个参数,如下所示:(
然后您可以将所有
TypeSafeEnum<...>
字段和参数替换为TEnum
)我很确定这也能解决您的实际问题。
由于
TypeSafeEnum
基类现在引用继承的枚举类,因此继承类的静态构造函数将运行,初始化值。Your idea will not work.
The static
List<TypeSafeEnum<TNameType, TValueType>> listEnums
field will be shared by allTypeSafeEnum
classes that have the same name and value types.To solve that problem, add a parameter for the actual enum class, like this:
(You can then replace all of your
TypeSafeEnum<...>
fields and parameters withTEnum
)I'm pretty sure that this will also solve your actual question.
Since the base
TypeSafeEnum
class now references the inherited enum class, the inherited class' static constructor will run, initializing the values.如果您只是使用一些静态功能,为什么还要使用实例呢?创建一个静态类,并具有一个静态“Initialize()”方法,您可以调用该方法来设置对象。
If you are just using some static functionality, why use an instance at all? Create a static class, and have a static 'Initialize()' method that you can call to set up your object.
在您尝试显式访问静态成员之前,不保证它们会被初始化。您可以通过创建显式静态构造函数(以避免 beforeFieldInit 行为)并显式访问静态方法(如虚拟 Init 方法)来强制静态初始化来解决此问题。
Static members are not guaranteed to be initialized until you attempt to explicitly access them. You can get around this by creating an explicit static constructor (to avoid beforeFieldInit behavior) and explicitly access a static method (like a dummy Init method) to force static initialization.