属性 - 按值还是参考?

发布于 2024-10-21 07:40:31 字数 669 浏览 7 评论 0原文

我有以下公共属性,它公开了 Arraylist:

public ArrayList SpillageRiskDescriptions
        {
            get
            {
                return _SpillageRiskDescriptions;
            }
            set
            {
                _SpillageRiskDescriptions = value;
            }
        }

在其他地方,我调用

SpillageRiskDescriptions.Add("VENTILATE AREA");
SpillageRiskDescriptions.Add("DO NOT ALLOW SPILLAGE TO ENTER MAINS");

这些似乎将元素添加到私有 ArrayList _SpillageRiskDescriptions(通过该属性),而我本来预计这会引起问题。因此,我认为属性返回对原始变量的引用而不是通过传递它是否正确?这是因为 ArrayList 是引用类型吗? int 也会发生同样的情况吗(例如?)

I've got the following public property which exposes an Arraylist:

public ArrayList SpillageRiskDescriptions
        {
            get
            {
                return _SpillageRiskDescriptions;
            }
            set
            {
                _SpillageRiskDescriptions = value;
            }
        }

Elsewhere I'm calling

SpillageRiskDescriptions.Add("VENTILATE AREA");
SpillageRiskDescriptions.Add("DO NOT ALLOW SPILLAGE TO ENTER MAINS");

These seem to be adding elements to the private ArrayList _SpillageRiskDescriptions (through the property) whereas I would've expected this to cause a problem. Therefore am I correct in thinking that properties return a reference to the original variable and not passing it by value? Is this because ArrayList is a reference type? Will the same happen with an int (for example?)

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

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

发布评论

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

评论(6

丢了幸福的猪 2024-10-28 07:40:32

其他答案已经正确回答了您的主要问题:引用类型的属性的是对实例<的引用 /em> 引用类型。

更大的问题是“现在你该怎么办?”想必您想要能够获取列表的代码能够更改列表。

这里有几个选项。

首先,无论您做什么,我都建议您立即停止使用 ArrayList,并开始使用更现代、更安全的类型来存储事物列表。 List 立即浮现在脑海中。

其次,属性的setter是否必须是公开的?您是否希望任何人都能够更改该列表?或者类型本身应该负责以某种方式更新它?我会考虑将设置器设为私有。

第三,我们为“琐碎”属性提供了更紧凑的语法。您可能会说

public List<string> SpillageListDescriptions { get; private set; }

,编译器将为您生成支持字段。

请注意,List 仍然允许突变。

如果所有客户端关心的是能够一次迭代列表中的一件事,那么你可以这样做:

private List<string> descriptions = whatever;
public IEnumerable<string> SpillageListDescriptions 
{ 
    get 
    {
        if (descriptions == null) yield break;
        foreach(var description in descriptions) 
            yield return description;
    }
}

现在调用者不可能改变列表,因为你给他们的只是一个迭代器它,不能访问列表本身。

或者你可以这样做:

private List<string> descriptions = whatever;
public IList<string> SpillageListDescriptions 
{ 
    get 
    {
        return new ReadOnlyCollection<string>(descriptions); 
    }
}

现在调用者有一个列表的只读视图,如果他们尝试修改它,就会抛出异常。

The other answers have correctly answered your primary question: that the value of a property of reference type is a reference to an instance of the reference type.

The larger question is "now what do you do about it?" Presumably you do not want code that can obtain the list to be able to change it.

There are several options here.

First, no matter what you do I recommend that you stop using ArrayList right now and start using a more modern, safe type for storing a list of things. List<string> comes immediately to mind.

Second, is it necessary that the setter of the property be public? Do you want just anyone to be able to change that list? Or should the type itself be responsible for updating it somehow? I'd consider making the setter private.

Third, we have a more compact syntax for a "trivial" property. You could be saying

public List<string> SpillageListDescriptions { get; private set; }

and the compiler will generate the backing field for you.

Note that List<string> still allows mutation.

If all the client cares about is being able to iterate over the list one thing at a time, then you can do this:

private List<string> descriptions = whatever;
public IEnumerable<string> SpillageListDescriptions 
{ 
    get 
    {
        if (descriptions == null) yield break;
        foreach(var description in descriptions) 
            yield return description;
    }
}

and now it is impossible for the caller to mutate the list, because all you're giving them is an iterator over it, not access to the list itself.

Or you could do:

private List<string> descriptions = whatever;
public IList<string> SpillageListDescriptions 
{ 
    get 
    {
        return new ReadOnlyCollection<string>(descriptions); 
    }
}

And now the caller has a read-only view of the list that will throw an exception if they attempt to modify it.

多情出卖 2024-10-28 07:40:32

C# 通过引用返回对象。

唯一不按值返回的是:

原始类型。
结构类型。
枚举。

C# returns objects by reference.

Only things that aren't returned by value are:

Primitive types.
Struct types.
Enums.

走走停停 2024-10-28 07:40:32

这与它本身是否是财产无关;它是属性的数据类型。在本例中,您使用的是 ArrayList,它是一个通过引用传递的类。如果该属性的类型为 int ,则它将按值传递。

It has nothing to do with whether it is a property per se; it is the data type of the property. In this case, you are using ArrayList which is a class that is passed by reference. If the property were typed as an int it would be passed by value.

皇甫轩 2024-10-28 07:40:32

属性实际上是两个方法的对 - setter 和 getter。它们按原样传递支持字段(或用作源/目标的任何内容)的值。因此,对于引用类型,传递引用,对于值类型,传递值。

// this is how the getter method looks like
public ArrayList get_SpillageRiskDescriptions()
{
    return _SpillageRiskDescriptions;
}

// this is how the setter method looks like
public void set_SpillageRiskDescriptions(ArrayList value)
{
    _SpillageRiskDescriptions = value;
}

请注意,通过将 ArrayList 实例分配到您的属性中,您基本上可以替换支持字段指向的 ArrayList 实例。

回答您的具体问题:

因此,我认为属性返回对原始变量的引用而不是通过传递它是否正确?

不,通过使用 getter,您不会获得对 _SpillageRiskDescriptions 字段的引用。您将获得该字段的,该字段是对(动态分配的)ArrayList 实例的引用。

这是因为 ArrayList 是引用类型吗?

是的,ArrayList 是一个引用类型,因此您会收到对特定 ArrayList 实例的引用。

int 也会发生同样的情况吗(例如?)

是的,也不是。 ,您将收到 int 字段的值。 int是一种值类型,因此如果您修改该值而不显式将其设置回来,则底层字段不会受到影响。

A property is actually a pair of two methods — a setter and a getter. They pass the value of the backing field (or whatever is used as the source / destination) as it is. Hence, for reference types the reference is passed, and for value types the value is passed.

// this is how the getter method looks like
public ArrayList get_SpillageRiskDescriptions()
{
    return _SpillageRiskDescriptions;
}

// this is how the setter method looks like
public void set_SpillageRiskDescriptions(ArrayList value)
{
    _SpillageRiskDescriptions = value;
}

Note that by assigning an ArrayList instance into your property you basically replace the ArrayList instance pointed to by the backing field.

To answer your particular questions:

Therefore am I correct in thinking that properties return a reference to the original variable and not passing it by value?

No, by using the getter you don't get a reference to the _SpillageRiskDescriptions field. You get the value of the field which is a reference to a (dynamically allocated) ArrayList instance.

Is this because ArrayList is a reference type?

Yes, ArrayList is a reference type and thus you receive the reference to the particular ArrayList instance.

Will the same happen with an int (for example?)

Yes and no. Yes, you will receive the value of an int field. And no, int is a value type, so if you modify the value without explicitly setting it back, the underlying field won't be affected.

太阳哥哥 2024-10-28 07:40:32

和房产没有任何关系。

在这种情况下,您将按值传递对数组列表的引用。

如果您执行类似的操作

      void AddSomethingToArrayList(ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions.Add("Something");
      }

,那么对数组列表的引用将被修改。

如果您要做类似的事情

      void ReassignArrayList(ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions = new ArrayList();
           spillageRiskDescriptions.Add("Something");
      }

,那么对数组列表的原始引用根本不会改变。

但是,如果您要通过引用传递引用(例如:),

      void ReassignArrayListByRef(ref ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions = new ArrayList();
           spillageRiskDescriptions.Add("Something");
      }

那么您的属性最终将得到一个包含单个项目的新数组列表。

It doesn't have anything to with the property.

In this case, you are passing a reference to the array list by value.

If you do something like

      void AddSomethingToArrayList(ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions.Add("Something");
      }

then the reference to the array list will be modified.

If you were to do something like

      void ReassignArrayList(ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions = new ArrayList();
           spillageRiskDescriptions.Add("Something");
      }

then the original reference to the array list would not be changed at all.

But if you were to pass the reference by reference such as in:

      void ReassignArrayListByRef(ref ArrayList spillageRiskDescriptions){
           spillageRiskDescriptions = new ArrayList();
           spillageRiskDescriptions.Add("Something");
      }

then your property would end up with a new array list with a single item.

月依秋水 2024-10-28 07:40:31

从技术上讲,它总是按值传递,但您必须了解正在传递的内容。由于它是引用类型,因此您将传递回引用(但按值)。

希望这是有道理的。您始终按值传回结果,但如果类型是引用,则您将按值传回引用,这意味着您可以更改对象,但不能更改它引用的对象。

Technically it's always by value, but you have to understand what is being passed. Since it's a reference type, you are passing a reference back (but by value).

Hope that makes sense. You always pass the result back by value, but if the type is a reference you are passing the reference back by value, which means you can change the object, but not which object it refers to.

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