c# - 有什么方法可以避免 C# 中的属性内联优化?

标签 c# stack-trace

所以我有一个旨在实现 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/

相关文章:

c# - 可空列表 <> 作为输出参数

java - Spring Boot 自定义错误页面堆栈跟踪

java - 创建没有堆栈跟踪的 NPE

python - 如何在Python中生成类似java的堆栈跟踪?

c# - 在Azure表存储中按标签查询

c# - 如何从 gridview 访问文本框文本到按钮 Onclick 事件

C# 套接字 : Do I really need so many separate threads

javascript - 如何在 Windows 8.1 触摸屏中处理 mouseover 和 mouseleave 事件

air - 如何在非 Debug模式下获取 Adob​​e AIR 全局运行时错误的堆栈跟踪?

logging - 将结果堆栈跟踪默认写入文件