所以我有一个旨在实现INotifyPropertyChanged的PropertyBag类.为了使这段代码尽可能干净地工作并避免用户错误,我使用堆栈来获取属性名称.请参阅,如果属性名称与实际属性完全不匹配,那么您将失败并且我正在尝试保护它.
所以,这是该类的示例用法:
public class MyData : PropertyBag { public MyData() { Foo = -1; } public int Foo { get { return GetProperty(); } set { SetProperty(value); } } }
基本PropertyBag的重要代码在这里:
public abstract class PropertyBag : INotifyPropertyChanged { protected T GetProperty() { string propertyName = PropertyName((new StackTrace()).GetFrame(1)); if (propertyName == null) throw new ArgumentException("GetProperty must be called from a property"); return GetValue (propertyName); } protected void SetProperty (T value) { string propertyName = PropertyName((new StackTrace()).GetFrame(1)); if (propertyName == null) throw new ArgumentException("SetProperty must be called from a property"); SetValue(propertyName, value); } private static string PropertyName(StackFrame frame) { if (frame == null) return null; if (!frame.GetMethod().Name.StartsWith("get_") && !frame.GetMethod().Name.StartsWith("set_")) return null; return frame.GetMethod().Name.Substring(4); } }
所以现在你已经看到了我的代码,我可以告诉你这个问题......在某些情况下,在发布版本中,"MyData"构造函数中的"Foo"setter似乎正在优化为内联为SetProperty(-1).不幸的是,这个内联优化失败了我的SetProperty方法,因为我不再从属性调用它!失败.看来我不能以这种方式依赖StackTrace.
任何人都可以答:找出更好的方法来做到这一点,但仍然避免将"Foo"传递给GetProperty和SetProperty?
B:想办法告诉编译器在这种情况下不优化?
在这里使用堆栈是缓慢且不必要的; 我只想使用:
get { return GetProperty("Foo"); } set { SetProperty("Foo", value); }
(提示:我已经使用自定义属性模型做了很多工作;我知道这很有效......)
另一个替代方法是对象键(使用引用相等来比较) - 很多ComponentModel
方法都是这样工作的,WF/WPF中的一些属性也是如此:
static readonly object FooKey = new object(); ... get { return GetProperty(FooKey); } set { SetProperty(FooKey, value); }
当然,您可以声明键的类型(带有Name
属性),并使用:
static readonly PropertyKey FooKey = new PropertyKey("Foo");
等等; 然而,要回答这个问题:用它标记它(但不要这样做):
[MethodImpl(MethodImplOptions.NoInlining)]
要么
[MethodImpl(MethodImplOptions.NoOptimization)]
要么
[MethodImpl(MethodImplAttributes.NoOptimization | MethodImplAttributes.NoInlining)]