强制C#编译器创建未使用的对象实例

强制C#编译器创建未使用的对象实例,c#,compiler-construction,instance,jit,C#,Compiler Construction,Instance,Jit,是的,这正是我想做的:)至少对于一个特定的类。 问题是,我创建了一个对象的静态实例,但没有直接使用它。由于我在构造函数中执行一些操作,比如将对象添加到列表中,因此在获取列表之前必须至少调用一次构造函数 我猜编译器只是优化了未使用的对象 必须有一个简单的解决方案:-/ 编辑 好吧,也许我错过了什么。让我发布我的代码。我为自定义枚举编写了一个类 public class TypeSafeEnum<TNameType, TValueType> {

是的,这正是我想做的:)至少对于一个特定的类。 问题是,我创建了一个对象的静态实例,但没有直接使用它。由于我在构造函数中执行一些操作,比如将对象添加到列表中,因此在获取列表之前必须至少调用一次构造函数

我猜编译器只是优化了未使用的对象

必须有一个简单的解决方案:-/

编辑

好吧,也许我错过了什么。让我发布我的代码。我为自定义枚举编写了一个类

        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)
            {
            }
        }
你可以简单地写

new YourObject();
这不会被优化掉。

但是,除非类的构造函数将自身保存在某个位置(例如,将对象添加到列表或静态字段,或将事件处理程序添加到其他内容),否则该对象可能会立即被垃圾收集。

首先,请验证编译器是否确实优化了代码。很可能,它真的没有:如果你的构造函数调用有副作用,编译器就没有权利去消除它

如果它确实得到了优化,您可以使用
GC.KeepAlive
方法来保证对象保持:

GC.KeepAlive( new MyObj() );

这个方法实际上什么都不做——它的主体是空的。但它的特殊之处在于它无法被优化。如果你用一些参数来调用它,那么这个参数也不能被优化。

如果你只是在使用一些静态功能,为什么要使用实例呢?创建一个静态类,并拥有一个静态“Initialize()”方法,您可以调用该方法来设置对象。

您的想法行不通

静态
List listEnums
字段将由所有具有相同名称和值类型的
TypeSafeEnum
类共享

要解决该问题,请为实际枚举类添加一个参数,如下所示:

public class TypeSafeEnum<TEnum, TName, TValue> where TEnum : TypeSafeEnum<TEnum, TName, TValue>
公共类TypeSafeEnum,其中TEnum:TypeSafeEnum
(然后,您可以将所有
TypeSafeEnum
字段和参数替换为
TEnum

我很确定这也将解决您的实际问题。

由于基本
TypeSafeEnum
类现在引用继承的enum类,继承类的静态构造函数将运行,初始化值。

在尝试显式访问静态成员之前,不保证初始化静态成员。您可以通过创建显式静态构造函数(以避免beforeFieldInit行为)并显式访问静态方法(如伪Init方法)以强制静态初始化来解决此问题。

也许您可以讨论一下您试图实现的目标;可能有其他解决方案?不存在“静态实例”。我想你的意思是你有一个静态变量,你可以通过创建一个类的实例来初始化它?@SLaks:为什么它会泄漏内存?使用keep-alive语句似乎很愚蠢。当调用实际向GC发出可以回收新创建的对象的信号时,为什么要让新对象保持活动状态呢。这就是它将“泄漏内存”的原因吗?因为对象永远不会被收集。这取决于对象是什么,它做什么,这可能是一个问题,也可能不是问题。抱歉,听起来很顽固,但正在努力理解。我从来不需要使用“保持活力”。为什么它永远不会被收集?备注部分指出,“KeepAlive方法除了延长作为参数传入的对象的生存期外,不执行任何操作,也不会产生任何副作用。”因此,传递新对象不会产生任何效果。这会愚弄GC让对象永远活着吗?@Slaks-
KeepAlive
只充当不透明的方法。一旦超出这个范围,它就什么也做不了。我认为在这种情况下,
KeepAlive
什么都不做。
KeepAlive
的典型用法是在方法(例如
Mutex
)的顶部初始化一个变量,该变量永远不会再碰,但在该方法退出之前,您确实不希望被垃圾收集。
KeepAlive
算作对变量的读取,因此必须保留该值。否则,来自未读取超过堆栈位置的变量的引用可能符合收集条件;我收回我的评论。谢谢你启发我,我明白了。塔克斯。那么,您有什么建议?OK list现在运行正常,但实际问题仍然存在:(如果未手动调用FileOptionEnum.Name,FileOptionEnum.GetNames()仍会给出一个空列表。您可以在基类的静态构造函数中使用反射。
public class TypeSafeEnum<TEnum, TName, TValue> where TEnum : TypeSafeEnum<TEnum, TName, TValue>