所以我有一个旨在实现INotifyPropertyChanged的PropertyBag类.为了使这段代码尽可能干净地工作并避免用户错误,我使用堆栈来获取属性名称.请参阅,如果属性名称与实际属性完全不匹配,那么您将失败并且我正在尝试保护它.
所以,这是该类的示例用法:
public class MyData : PropertyBag
{
public MyData()
{
Foo = -1;
}
public int Foo
{
get { return GetProperty<int>(); }
set { SetProperty(value); }
}
}
Run Code Online (Sandbox Code Playgroud)
基本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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在你已经看到了我的代码,我可以告诉你这个问题......在某些情况下,在发布版本中,"MyData"构造函数中的"Foo"setter似乎正在优化为内联为SetProperty(-1).不幸的是,这个内联优化失败了我的SetProperty方法,因为我不再从属性调用它!失败.看来我不能以这种方式依赖StackTrace.
任何人都可以答:找出更好的方法来做到这一点,但仍然避免将"Foo"传递给GetProperty和SetProperty?
B:想办法告诉编译器在这种情况下不优化?
Mar*_*ell 14
在这里使用堆栈是缓慢且不必要的; 我只想使用:
get { return GetProperty<int>("Foo"); }
set { SetProperty("Foo", value); }
Run Code Online (Sandbox Code Playgroud)
(提示:我已经使用自定义属性模型做了很多工作;我知道这很有效......)
另一个替代方法是对象键(使用引用相等来比较) - 很多ComponentModel方法都是这样工作的,WF/WPF中的一些属性也是如此:
static readonly object FooKey = new object();
...
get { return GetProperty<int>(FooKey); }
set { SetProperty(FooKey, value); }
Run Code Online (Sandbox Code Playgroud)
当然,您可以声明键的类型(带有Name属性),并使用:
static readonly PropertyKey FooKey = new PropertyKey("Foo");
Run Code Online (Sandbox Code Playgroud)
等等; 然而,要回答这个问题:用它标记它(但不要这样做):
[MethodImpl(MethodImplOptions.NoInlining)]
Run Code Online (Sandbox Code Playgroud)
要么
[MethodImpl(MethodImplOptions.NoOptimization)]
Run Code Online (Sandbox Code Playgroud)
要么
[MethodImpl(MethodImplAttributes.NoOptimization
| MethodImplAttributes.NoInlining)]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4312 次 |
| 最近记录: |