Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义属性以确保封装_C#_.net_Attributes - Fatal编程技术网

C# 自定义属性以确保封装

C# 自定义属性以确保封装,c#,.net,attributes,C#,.net,Attributes,我开始研究自定义属性,我想到了以下想法:如果我可以创建一个属性,将变量的使用限制在它所支持的属性上,该怎么办 [RestrictToProperty("Foo")] private object _foo; public object Foo { get { return _foo; } set { _foo = value; OnFooChanged(EventArgs.Empty); } } public object NotF

我开始研究自定义属性,我想到了以下想法:如果我可以创建一个属性,将变量的使用限制在它所支持的属性上,该怎么办

[RestrictToProperty("Foo")]
private object _foo;
public object Foo
{
    get { return _foo; }
    set
    {
        _foo = value;
        OnFooChanged(EventArgs.Empty);
    }
}
public object NotFoo
{
    get { return _foo; }  // Warning
    set { _foo = value; } // Warning
}
public void Bar()
{
    _foo = new object();  // Warning
}

// Warning: 'MyClass._foo' should not be used outside of property 'Foo'
我相信这是可能的,因为
过时的
做了类似的事情

[Obsolete]
private object _foo;
public void Bar()
{
    _foo = new object(); // Warning: 'MyClass._foo' is obsolete
}

不幸的是,我不知道该怎么做,除了简单的运行时属性教程之外,我找不到更多。这可能吗?如果是这样,我从哪里开始?

您应该能够编写一条规则,使其成为错误或警告。

不,这是不可能的
ObsoleteAttribute
在C#规范中有一个关于编译器本身如何响应它的定义

可以通过使用隐式将变量的使用限制为单个属性

编辑:如果希望在getter和setter中独立处理特殊逻辑,可以尝试以下代码。这对我来说似乎非常讨厌

public class Test
{

  private PrivateMembers Members { get; set; }

  public object Foo
  {
    get
    {
      return Members.Foo;
    }
    set
    {
      Members.Foo = value;
      // Do something else here.
    }
  }

  private class PrivateMembers
  {
    public object Foo { get; set; }
  }
}

不幸的是,这是不可能的。不过,您可能想探索一下,这是一个面向方面的.NET IL-weaver——基本上它让您的源代码经过一个额外的编译层,可以注入所有额外的仪式。

稍微偏离主题,但您可以(ab)使用
过时的
属性来实现您需要的功能

将支持字段标记为已过时,以便编译器在您尝试访问它时生成警告,然后在属性getter/setter中生成警告。(相关警告为和。)


这确实让人感觉像是一个令人讨厌的黑客行为,我真的不推荐这样做。还有其他更好的选择。例如,自定义FxCop规则、单元测试、良好的代码注释等。

这令人失望。请参阅我对stakx关于自动实现属性的评论。@Daniel:我编辑了我的答案,以提供另一个令人讨厌的替代方案。我不确定这是如何实现我的目的的。。。如果没有
Foo
属性,您仍然可以访问
Members.Foo
,不是吗?@Daniel:是的,它肯定不能完全满足您的需要。+1表示完全相同的想法:)不幸的是,自定义FxCop规则可能与此非常接近(
过时
的行为无法复制,除非你想编写自己的c#编译器)是的,我对它的破解并不感兴趣。我只是想知道我是否能想出一个优雅的解决方案。不过,谢谢你的想法。这是一个很好的例子,说明你能做什么。这其实很聪明。
public class Test
{

  private PrivateMembers Members { get; set; }

  public object Foo
  {
    get
    {
      return Members.Foo;
    }
    set
    {
      Members.Foo = value;
      // Do something else here.
    }
  }

  private class PrivateMembers
  {
    public object Foo { get; set; }
  }
}
[Obsolete("Backing field should not be used outside of property")]
private object _foo;

public object Foo
{
    #pragma warning disable 612, 618
    get { return _foo; }
    set
    {
        _foo = value;
        OnFooChanged(EventArgs.Empty);
    }
    #pragma warning restore 612, 618
}