繁体   English   中英

C# 中的“只读”属性访问器

[英]“Read only” Property Accessor in C#

我有以下 class:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

   public ArrayList MyList
   {
       get { return mMyList;}
   }
}

我希望用户能够获得 mMyList,这就是为什么我通过属性公开“get”但是我不希望他们对 object(即 MyList.Add(new Class());) 进行更改以使其回到我的 class。

我想我可以返回 object 的副本,但这可能会很慢,我正在寻找一种方法来提供编译时错误,通知用户他们不应该期望能够从财产。

这可能吗?

使用 ArrayList,您将受到相当的限制,因为 BCL 中没有只读的非泛型集合 class。 快速而肮脏的解决方案是返回一种 IEnumerable。

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

这实际上不会阻止某人投射到 ArrayList 但默认情况下也不允许编辑

您可以通过调用 ArrayList.ReadOnly 返回一个有效的只读列表。 然而,它的返回类型是 ArrayList,因此用户仍然可以使用.Add 进行编译,但会产生运行时错误。

使用ArrayList.ReadOnly()方法构造并返回列表周围的只读包装器。 它不会复制列表,而只是在其周围创建一个只读包装器。 为了获得编译时检查,您可能希望按照@Jared 的建议将只读包装器作为 IEnumerable 返回。

public IEnumerable MyList
{
     get { return ArrayList.ReadOnly(mMyList); }
}

只读集合只是一个带有防止修改集合的包装器的集合。 如果对基础集合进行了更改,则只读集合会反映这些更改。

此方法是 O(1) 操作。

参考

只是为了扩展 JaredPar 的答案。 正如他所说,返回实际的支持字段并不完全安全,因为用户仍然能够将IEnumerable动态转换回ArrayList

我会写这样的东西来确保不对原始列表进行任何修改:

public IEnumerable MyList
{
    get
    {
         foreach (object o in mMyList)
             yield return o;
    }
}

再说一次,我可能还会使用通用列表( IEnumerable<T> )来保证类型安全。

使用ReadOnlyCollection

return new ReadOnlyCollection<object>(mMyList)

您还可以将ReadOnlyCollection字段,它将自动反映基础列表中的更改。 这是最有效的解决方案。

如果您知道 mMyList 仅包含一种类型的 object(例如,它只有 DateTimes),您可以返回ReadOnlyCollection<DateTime> (或其他类型)以获得额外的类型安全。 如果您使用的是 C# 3,您可以简单地编写

return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())

但是,这不会自动更新底层列表,效率也较低(它将复制整个列表)。 最好的选择是使 mMyList 成为通用List<T> (例如, List<DateTime>

您应该将返回值包装在只读集合中。

可从 .NET v2.0 获得

    public ArrayList MyList { get; private set; }

只需将属性设为 Sealed(或 VB.NET 中的 NotInheritable)并且只读,如下所示:

   public sealed readonly ArrayList MyList
   {
       get { return mMyList;}
   }

也不要忘记将支持字段设为只读:

   private readonly ArrayList mMyList;

但为了初始化 mMyList 的值,您必须仅在构造函数中对其进行初始化,如下例所示:

public SampleClass()
{
   // Initialize mMyList
   mMyList = new ArrayList();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM