【问题标题】:Is named indexer property possible? [duplicate]命名索引器属性是否可能? [复制]
【发布时间】:2010-07-20 19:16:22
【问题描述】:

假设我在类中有一个数组或任何其他集合,以及一个返回它的属性,如下所示:

public class Foo
{
    public IList<Bar> Bars{get;set;}
}

现在,我可以这样写吗:

public Bar Bar[int index]
{
    get
    {
        //usual null and length check on Bars omitted for calarity
        return Bars[index];
    }
}

【问题讨论】:

  • Bars 属性已经支持索引,所以我对你想要完成的事情有点困惑。
  • 当然@Anthony Foo f=new Foo(); f.Bars[0]; 哇,我想我现在该睡觉了!
  • @AnthonyPegram 你可能不想暴露Bars。它可能是一个不应该成为Foos 公共API 一部分的实现细节。此外,这暴露的不仅仅是Bars 的索引属性。 Bars 可能是高度有状态的,暴露它可能会导致用户违反Foo 承诺的不变量。
  • 虽然几天后有人问了另一个问题stackoverflow.com/questions/3344620/…,但浏览量更多,但我要关闭这个问题。
  • 请参阅github.com/dotnet/csharplang/issues/471 以获取添加此功能的请求以及支持和反对它的所有参数。直到今天,开发人员都拒绝添加它,因为他们没有看到该语言有足够的好处。

标签: c# properties indexed-properties


【解决方案1】:

不 - 您不能在 C# 中编写命名索引器。从 C# 4 开始,您可以将它们用于 COM 对象,但不能编写它们。

然而,正如您所注意到的,foo.Bars[index] 无论如何都会做您想做的事......这个答案主要是为了未来的读者。

详细说明:公开具有索引器的某种类型的 Bars 属性可以实现您想要的,但您应该考虑如何公开它:

  • 您希望调用者能够用不同的集合替换集合吗? (如果不是,请将其设为只读属性。)
  • 您希望调用者能够修改集合吗?如果是这样,怎么做?只是更换项目,或添加/删除它们?您需要对此进行任何控制吗?这些问题的答案将决定您要公开的类型 - 可能是只读集合,或具有额外验证的自定义集合。

【讨论】:

  • 你能不能复制这里使用的相同样式msdn.microsoft.com/en-us/library/146h6tk5.aspx 并且取决于你如何实现该方法得到相同的结果?
  • @Gage:我不确定你在说什么......据我所知,这并没有创建命名索引器......
  • @JonSkeet 使用foo.Bars[index],正如您在此处所建议的那样,会将Bars 暴露给Foo 的消费者。这意味着Foo 实际上无法控制与Bars 相关的任何不变量。此外,Foo 的所有消费者现在都与Bars 强耦合。在这种情况下,GetBarSetBar 方法会更好,至少在信息隐藏方面是这样。
  • @Undreren:这取决于您是否真的想要隐藏信息。您也可以将其公开为ReadOnlyCollection&lt;T&gt; - 或者IList&lt;T&gt; 可能已经成为 ReadOnlyCollection&lt;T&gt;。为了访问,只需要一个 getter - 是否还有一个 setter 取决于要求。我不想在这方面过于武断——有时对所有相关人员来说,暴露一个 setter 和一个 getter 是最简单的;有时仍然允许收集操作的吸气剂;有时是只读访问权限。
  • @Undreren:我将编辑答案以提及这一点,但基本上问题是关于 C# 中是否存在命名索引器,答案是否定的。
【解决方案2】:

【讨论】:

    【解决方案3】:

    您可以使用显式实现的接口,如下所示: Named indexed property in C#?(见回复中显示的第二种方式)

    【讨论】:

      【解决方案4】:
      public class NamedIndexProp
      {
          private MainClass _Owner;
          public NamedIndexProp(MainClass Owner) { _Owner = Owner;
          public DataType this[IndexType ndx]
          {
              get { return _Owner.Getter(ndx); }
              set { _Owner.Setter(ndx, value); }
          }
      }
      public MainClass
      {
          private NamedIndexProp _PropName;
          public MainClass()
          {
             _PropName = new NamedIndexProp(this);
          }
          public NamedIndexProp PropName { get { return _PropName; } }
          internal DataType getter(IndexType ndx)
          {
              return ...
          }
          internal void Setter(IndexType ndx, DataType value)
          {
             ... = value;
          }
      }
      

      【讨论】:

      • 您需要在答案中添加一些解释以使其更好
      • 非常不言自明,使用源卢克!
      【解决方案5】:

      根据您真正要寻找的内容,它可能已经为您完成了。如果您尝试在 Bars 集合上使用索引器,它已经为您完成了::

      Foo myFoo = new Foo();
      Bar myBar = myFoo.Bars[1];
      

      或者,如果您想获得以下功能:

      Foo myFoo = new Foo();
      Bar myBar = myFoo[1];
      

      然后:

      public Bar this[int index]
      {
          get { return Bars[index]; }
      }
      

      【讨论】:

      • 我认为 'this' 不是命名属性。
      • @wishmaster35 不是。我不知道为什么这个答案被接受了,因为这是一种设计味道:它将Foo 的消费者与Bars 强烈耦合。在某些情况下,这可能无关紧要,但现在Foo 无法控制自己的私人数据;大家可以直接修改Bars,在Foo左右。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      相关资源
      最近更新 更多