所以我有一个旨在实现 INotifyPropertyChanged 的 PropertyBag 类。为了使此代码尽可能干净地工作并避免用户错误,我使用堆栈来获取属性名称。你看,如果属性名称与实际属性不完全匹配,那么你就会失败,我正在努力避免这种情况。
因此,这是该类的示例用法:
public class MyData : PropertyBag
{
public MyData()
{
Foo = -1;
}
public int Foo
{
get { return GetProperty<int>(); }
set { SetProperty(value); }
}
}
基础 PropertyBag 的重要代码在这里:
public abstract class PropertyBag : INotifyPropertyChanged
{
protected T GetProperty<T>()
{
string propertyName = PropertyName((new StackTrace()).GetFrame(1));
if (propertyName == null)
throw new ArgumentException("GetProperty must be called from a property");
return GetValue<T>(propertyName);
}
protected void SetProperty<T>(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。
任何人都可以
A:想出一个更好的方法来做到这一点,但仍然避免将“Foo”传递给 GetProperty 和 SetProperty?
B:想办法告诉编译器在这种情况下不要优化?
最佳答案
在这里使用堆栈很慢而且没有必要;我会简单地使用:
get { return GetProperty<int>("Foo"); }
set { SetProperty("Foo", value); }
(提示:我已经对自定义属性模型做了很多工作;我知道这很有效...)
另一种选择是对象键(使用引用相等性进行比较)- 许多 ComponentModel
都是这样工作的,WF/WPF 中的一些属性也是如此:
static readonly object FooKey = new object();
...
get { return GetProperty<int>(FooKey); }
set { SetProperty(FooKey, value); }
当然,您可以为键声明一个类型(使用 Name
属性),并使用它:
static readonly PropertyKey FooKey = new PropertyKey("Foo");
等;然而,要回答这个问题:标记它(但不要这样做):
[MethodImpl(MethodImplOptions.NoInlining)]
或
[MethodImpl(MethodImplOptions.NoOptimization)]
或
[MethodImpl(MethodImplAttributes.NoOptimization
| MethodImplAttributes.NoInlining)]
关于c# - 有什么方法可以避免 C# 中的属性内联优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/557643/