访问汽车属性中的支持字段

发布于 2024-07-14 15:32:45 字数 633 浏览 11 评论 0原文

有什么方法可以访问属性的支持字段以进行验证、更改跟踪等?

像下面这样的事情可能吗? 如果没有,是否有计划将其纳入 .NET 4 / C# 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

我遇到的主要问题是,使用自动属性不允许在验证等方面具有与具有显式支持字段的属性相同的灵活性。 然而,在某些情况下,显式支持字段的缺点是允许包含它的类访问支持字段,而该类应该访问和重用属性的验证、更改跟踪等,就像可能访问的任何其他类一样财产的外部。

在上面的示例中,对支持字段的访问将限定在属性范围内,从而防止规避属性验证、更改跟踪等。

编辑: 我已更改 支持字段> 到< 关键字>. 我会提出一个类似于 value 的新关键字。 field 会做得很好,尽管我确信它已在许多现有代码中使用。

Is there any way to access the backing field for a property in order to do validation, change tracking etc.?

Is something like the following possible? If not is there any plans to have it in .NET 4 / C# 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

The main issue I have is that using auto properties doesn't allow for the same flexibility in validation etc. that a property with a explicit backing field does. However an explicit backing field has the disadvantage in some situations of allowing the class it is contained in to access the backing field when it should be accessing and reusing the validation, change tracking etc. of the property just like any other class that may be accessing the property externally.

In the example above access to the backing field would be scoped to the property thus preventing circumvention of the property validation, change tracking etc.

Edit: I've changed < Backing Field > to < Keyword >. I would propose a new keyword similar to value. field would do nicely although I'm sure it's being used in a lot of existing code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

栩栩如生 2024-07-21 15:32:45

不,没有。 如果您想访问支持字段,请不要使用自动属性并推出您自己的属性。

我同意,如果有一个只能由该属性访问而不能由班级其他成员访问的字段,那就太好了。 我会一直使用它。

No there isn't. If you want to access the backing field, then don't use auto properties and roll your own.

I agree that it would be great to have a field that was only accessible by the property and not by the rest of the class. I would use that all the time.

酒废 2024-07-21 15:32:45

正如MSDN所述:

“在 C# 3.0 及更高版本中,自动实现
属性进行属性声明
没有额外逻辑时更简洁
在属性访问器中是必需的。
它们还允许客户端代码创建
对象 当您将属性声明为
如以下示例所示,
编译器创建一个私有的、匿名的
只能访问支持字段
通过属性的获取和设置
访问器。”

由于您的访问器中有额外的逻辑,因此在您的场景中不适合使用自动实现的属性。

支持字段确实存在,但它被赋予了一个损坏的名称以阻止您轻松引用它 - 这个想法是您永远不要直接引用该字段,出于兴趣,您可以使用 Reflector 反汇编代码并发现字段名称,但我建议您不要直接使用该字段,因为该名称确实可能是不稳定的,所以你的代码可能随时崩溃。

As the MSDN states:

"In C# 3.0 and later, auto-implemented
properties make property-declaration
more concise when no additional logic
is required in the property accessors.
They also enable client code to create
objects When you declare a property as
shown in the following example, the
compiler creates a private, anonymous
backing field can only be accessed
through the property's get and set
accessors."

Since you have additional logic in you accessors, the use of auto-implemented properties is not appropriate in your scenario.

While the backing field does exist, it is given a mangled name to stop you referencing it easily - the idea is that you never reference the field directly. For interests sake, you can use Reflector to disassemble your code and discover the field name, but I would recommend you not use the field directly as this name may indeed be volatile, so your code could break at any time.

歌入人心 2024-07-21 15:32:45

阅读了您在梅尔达德回答中的评论后,我想我更好地理解了您的问题。

您似乎担心开发人员访问他们正在编写的类中的私有状态、绕过验证逻辑等的能力。这表明状态根本不应该包含在类中。

我建议采取以下策略。 编写一个表示 ValidatedValue 的通用类。 此类仅保存支持值,并且仅允许通过 get 和 set 方法进行访问/更改。 委托被传递到 ValidatedValue 来表示验证逻辑:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

当然,您可以根据需要添加更多委托(例如,支持更改前/更改后通知)。

您的类现在将使用 ValidatedValue 代替您的属性的后备存储。

下面的示例显示了一个类 MyClass,其整数经验证小于 100。请注意,引发异常的逻辑位于 MyClass 中,而不是 ValidatedValue 中。 这允许您执行依赖于 MyClass 中包含的其他状态的复杂验证规则。 Lambda 表示法用于构造验证委托 - 您可以改为绑定到成员函数。

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

希望有所帮助 - 有点偏离原来的主题,但我认为这更符合您的实际担忧。 我们所做的是将验证逻辑从属性中取出并放在数据上,这正是您想要的地方。

Having read your comments in Mehrdad's answer, I think I understand your problem a bit better.

It appears that you are concerned about the ability of the developer to access private state in the class they are writing, bypassing your validation logic, etc. This suggests that the state should not be contained in the class at all.

I would suggest the following strategy. Write a generic class that represents a ValidatedValue. This class holds only the backing value and only allows access/mutation via get and set methods. A delegate is passed to the ValidatedValue to represent the validation logic:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

You could, of course, add more delegates as required (eg, to support pre/post change notification).

Your class would now use the ValidatedValue in place of a backing store for your property.

The example below shows a class, MyClass, with an integer that is validated to be less than 100. Note that the logic to throw an exception is in MyClass, not the ValidatedValue. This allows you to do complex validation rules that depend on other state contained in MyClass. Lambda notation was used to construct the validation delegate - you could have bound to a member function instead.

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

Hope that helps - somewhat off the original topic, but I think it's more inline with your actual concerns. What we have done is taken the validation logic away from the property and put it on the data, which is exactly where you wanted it.

暖树树初阳… 2024-07-21 15:32:45

不,但你可以在子类中:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}

No, but you can in a subclass:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}
我也只是我 2024-07-21 15:32:45

如果你要这样做,为什么要使用自动属性?!

一个简单的属性早在 1.0 就已经做到了。 我认为为每种特殊情况增加语言的复杂性是没有意义的。 您要么需要该属性来执行简单的存储/检索模型,要么需要更多。 在后一种情况下,普通属性就可以了。

If you're gonna do so, why you are using auto properties?!

A simple property has done it way back in 1.0. I don't think it makes sense to add complexity to the language for every special case. You either need the property to do plain store/retrieve model or need more than that. In the latter case, a normal property will do.

夏见 2024-07-21 15:32:45

恐怕你不能这样做。 这就是我开始编写 MoXAML Power Toys 的原因之一,以提供以下功能:将自动属性转换为通知属性。

You can't do this I'm afraid. That's one of the reasons I started writing MoXAML Power Toys, to provide the ability to convert automatic properties into Notify properties.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文