Able to modify private member outside the class?

2019-08-17 07:09发布

问题:

I came across the situation where i am able to modify the private members of the class outside. Here is my class:

public class MyClass
{
    private List<string> _myClassMember = null;

    public MyClass()
    {
        _myClassMember = new List<string>();
    }

    public List<string> GetClassMembers()
    {
        return _myClassMember;
    }

    public void PrintMembers()
    {
        Console.WriteLine("No of items in member {0}", _myClassMember.Count.ToString());
    }
}

This is how it has been called:

class Program
{
    static void Main(string[] args)
    {
        MyClass cls = new MyClass();
        cls.PrintMembers();
        IList<string> lst = cls.GetClassMembers();
        lst.Add("Item1");
        lst.Add("Item2");
        cls.PrintMembers();
    }
}

It prints as follows:

No of items in member 0
No of items in member 2

is that correct being able to update the private member outside ?

回答1:

Yes. It is just the reference that is private. If you share that reference. Then external code is free to modify its content.

If you do not want external code to modify the content, then use an immutable collection class instead.

Whilst you can modify the contents of the list referenced by myClassMember, what you can't do from outside the class is change the list that myClassMember points to.



回答2:

This is the second time this question has come up recently.

The correct way to think about this is that the data is not the thing that is private. The name is the thing that is private. If you choose to share the data outside of the class somehow, that's not breaking encapsulation. The thing that is actually private is the name _myClassMember, which only refers to the field in code that is inside the class.

See

Interface behavior is dfferent in VB.Net

for more details.



回答3:

It is the expected behavior in C#. List is what is called a reference type, meaning that when you return it from a function you are actually returning a reference to the object inside your class. This allows you to modify it.

Here is a link explaining the difference between reference types and value types:

Click here

Here is an example of what you could do to prevent modification:

public class MyClass
{
    private List<string> _myClassMember = null;

    public MyClass()
    {
        _myClassMember = new List<string>();
    }

    public IReadOnlyList<string> GetClassMembers()
    {
        return _myClassMember.AsReadOnly();
    }

    public void PrintMembers()
    {
        Console.WriteLine("No of items in member {0}", _myClassMember.Count.ToString());
    }
}


回答4:

I think it is not correct. The concept of private member is that you can not access it directly in a way such as

cls._myClassMember.Add("Item1");

But since you are calling

cls.GetClassMembers();

it returns the member of the class, and then you can do modifications to it.



回答5:

Yes, this is perfectly legal. If you wanted to have access to a private variable outside of the class, you'd usually use a property (get/set):

private List<string> _myClassMember = null;

public List<string> MyClassMember
{
    get { return _myClassMember; }
    set { _myClassMember = value; }
}

Remove the set portion of the property if you want others to be able to add/remove items but not actually assign a new list (or null) to _myClassMember.



标签: c# .net oop