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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/619396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:30:05  来源:igfitidea点击:

"Read only" Property Accessor in C#

c#.netpropertiesreadonlyaccessor

提问by cjserio

I have the following class:

我有以下课程:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

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

I want users to be able to get mMyList which is why i exposed the "get" via a property however i don't want changes they make to the object (ie. MyList.Add(new Class());) to make its way back into my class.

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

I guess i can return a copy of the object but that may be slow and i'm looking for a way that will provide a compile-time error informing the user that they shouldn't expect to be able to modify the returned value from the Property.

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

Is this possible?

这可能吗?

采纳答案by JaredPar

With an ArrayList you are fairly limited because there is no readonly non-generic collection class in the BCL. The quick and dirty solution is to return a type of IEnumerable.

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

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

This won't actually prevent someone from casting to ArrayList but it won't allow edits by default either

这实际上不会阻止某人转换为 ArrayList,但默认情况下也不允许编辑

You can return an effectively readonly list by calling ArrayList.ReadOnly. However it's return type is an ArrayList so the user would still be able to compile with .Add but it would produce a runtime error.

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

回答by Mehrdad Afshari

You should wrap the return value in a read only collection.

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

回答by tvanfosson

Use the ArrayList.ReadOnly()method to construct and return a read-only wrapper around the list. it won't copy the list, but simply make a read-only wrapper around it. In order to get compile-time checking, you probably want to return the read-only wrapper as IEnumerable as @Jared suggests.

使用ArrayList.ReadOnly()方法构造并返回列表周围的只读包装器。它不会复制列表,而是简单地围绕它制作一个只读包装器。为了进行编译时检查,您可能希望像@Jared 建议的那样将只读包装器作为 IEnumerable 返回。

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

A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection. If changes are made to the underlying collection, the read-only collection reflects those changes.

This method is an O(1) operation.

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

该方法是一个 O(1) 操作。

Reference

参考

回答by Eriawan Kusumawardhono

Just make the property as Sealed (or NotInheritable in VB.NET) and readonly, like this:

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

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

Also don't forget to make the backing field as readonly:

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

   private readonly ArrayList mMyList;

But in order to initialize the value of mMyList, you must initialize it ONLY in the constructor, as in this example:

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

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

回答by Tom Lokhorst

Just to expand on JaredPar's answer. As he said, returning the actual backing field is not completely safe, since the user is still able to dynamically cast the IEnumerableback to an ArrayList.

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

I would write something like this to be sure no modifications to the original list are made:

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

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

Then again, I would probabily also use a generic list (IEnumerable<T>) to be completely type safe.

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

回答by SLaks

Use a ReadOnlyCollection.

使用一个ReadOnlyCollection.

return new ReadOnlyCollection<object>(mMyList).

return new ReadOnlyCollection<object>(mMyList).

You can also make the ReadOnlyCollectiona field, and it will automatically reflect changes in the underlying list. This is the most efficient solution.

您还可以创建ReadOnlyCollectiona 字段,它会自动反映底层列表中的更改。这是最有效的解决方案。

If you know that mMyList only contains one type of object (eg, it has nothing but DateTimes), you can return a ReadOnlyCollection<DateTime>(or some other type) for additional type safety. If you're using C# 3, you can simply write

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

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

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

However, this will not automatically update with the underlying list, and is also less efficient (It will copy the entire list). The best option is to make mMyList a generic List<T>(eg, a List<DateTime>)

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

回答by wloescher

Available from .NET v2.0

从 .NET v2.0 可用

    public ArrayList MyList { get; private set; }