C# 私有成员可见性
我们的商业模式中有一个学生课程。令我感到奇怪的是,如果我们从另一个学生操纵一个学生,则学生的私人成员是可见的,这是为什么?
class Program {
static void Main(string[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.SeePrivatePropertiesAndFields(s2);
}
}
public class Student {
private String _studentsPrivateField;
public Student() {
_studentsPrivateField = DateTime.Now.Ticks.ToString();
}
public void SeePrivatePropertiesAndFields(Student anotherStudent) {
//this seems like these should be private, even from the same class as it is a different instantiation
Console.WriteLine(anotherStudent._studentsPrivateField);
}
}
我可以对此的设计考虑/影响有一些想法吗?看来你不能向你的兄弟姐妹隐瞒信息。有没有办法将字段或成员标记为对同一类的其他实例隐藏?
We have a Student class in our business model. something struck me as strange, if we are manipulating one student from another student, the students private members are visible, why is this?
class Program {
static void Main(string[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.SeePrivatePropertiesAndFields(s2);
}
}
public class Student {
private String _studentsPrivateField;
public Student() {
_studentsPrivateField = DateTime.Now.Ticks.ToString();
}
public void SeePrivatePropertiesAndFields(Student anotherStudent) {
//this seems like these should be private, even from the same class as it is a different instantiation
Console.WriteLine(anotherStudent._studentsPrivateField);
}
}
Can i have some thoughts on the design considerations/implications of this. It seems that you can't hide information from your siblings. Is there a way to mark a field or member as hidden from other instances of the same class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
有一个简单的方法可以确保这一点:
不要与同一类的其他实例的私有成员搞乱。
说真的 - 您是编写
Student
代码的人。There's an easy way to ensure this:
Don't mess around with private members of other instances of the same class.
Seriously - you're the one writing the
Student
code.确保这一点的最简单方法是对接口进行编程,例如:
由于 ExamineStudentsMembers 尝试访问私有字段,这将不再编译。
The easiest way to ensure this is to program to an interface, such as:
This will no longer compile due to ExamineStudentsMembers trying to access a private field.
如果您正在编写该类,则可以完全控制它,因此如果您不希望一个对象能够修改另一个对象,请不要编写该功能。
类通常会在其他实例中使用私有变量来实现高效的比较和复制功能。
If you are writing the class, you have complete control over it, so if you don't want one object to be able to modify another, don't write in that functionality.
Classes will often use private variables in other instances to implement efficient comparison and copy functions.
当这样的措辞时,访问同级的私有数据可能看起来是错误的:
但是,对于需要此类功能的方法来说,这似乎并不奇怪。什么方法需要访问兄弟姐妹的私有数据?比较方法(特别是 equals)和数据结构中的对象(例如树或链表)。
比较方法通常直接比较私有数据而不仅仅是公共数据。
对于构成链表、图或树的一类节点,能够访问兄弟节点的私有数据正是所需要的。已知的代码(类的一部分)可以修改数据结构,但数据结构之外的代码无法触及内部结构。
有趣的是,与首次开发该语言功能时相比,这两种情况在日常编程中不太常见。早在 20 世纪 90 年代和 2000 年代初,在 C++ 中,构建自定义数据结构和比较方法更为常见。也许现在是重新考虑私人成员的好时机。
Accessing a sibling's private data may seem wrong when phrased like:
However, it doesn't seem so odd for methods which require this sort of functionality. What methods require accessing a sibling's private data? Comparison methods (in particular equals) and objects in a data structure (say a tree or linked list).
Comparison methods often compare private data directly rather than just the public data.
For a class of nodes that make up a linked list, graph or tree, being able to access a sibling's private data is exactly what is needed. Code in the know (part of the class) can tinker around with the data structure, but code outside of the data structure cannot touch the internals.
It is interesting to note that these two cases are less common in day-to-day programming than when this language feature were first developed. Back in 1990s and early 2000s, in C++ it would have been much more common to build custom data structures and comparison methods. Perhaps it is a good time to reconsider private members.
我喜欢第二点,你可以看,但不要碰那些私人成员。
你应该说这很有趣,我曾经认识一位老师,他说他经常在决定哪些课程可以的问题上遇到问题看看成员们以及哪些他实际上可以和他们一起玩。
i like the second point, you can look, but dont touch those private members.
it's funny you should say that, i knew a teacher once and he said he often had a problem deciding what classes it was ok to look at the members and which ones he could actually have a play with.
对象只是一段数据;该类包含功能。成员方法只是编译器玩的一个好技巧;它实际上更像是带有隐含参数的静态方法(有点像扩展方法)。考虑到这一点,保护对象免受彼此影响就没有任何意义了。你只能保护班级免受彼此的侵害。所以它以这种方式运作是很自然的。
An object is just a piece of data; the class contains the functionality. A member method is just a nice trick the compiler plays; it's really more like a static method with an implied argument (sort of like extension methods). With that in mind, protecting objects from each other doesn't make any sense; you can only protect classes from each other. So it's natural that it works that way.
不,这是必要的,方法代码不特定于实例,它仅特定于对象的类型。 (虚拟方法)或变量的声明类型(对于非虚拟方法)。另一方面,非静态字段是特定于实例的......这就是您拥有实例级隔离的地方。
静态方法和非静态方法之间的唯一区别是静态方法不允许访问其他基于实例的(非静态)方法或字段。任何可以在不进行修改的情况下变为静态的方法都不会因使其成为静态而受到任何影响,除非强制编译器在使用基于实例的语法调用的任何地方抛出错误。
No, this is necessary, the method code is not specific to the instance, it is only specific to the type of the object. (virtual methods) or the declared type of the variable (for non-virtual methods). The non-static fields, on the other hand, are instance specific... That's where you have instance-level isolation.
The only difference between a static method and a non-static method is that the static method is not allowed to access other instance based (non-static) methods or fields. Any method that CAN be made static without modification will not be affected in any way by making it static, except to force compiler to throw errors anywhere it was called using instance-based syntax.
如果您打算检查给定学生的信息,那么我会将方法更改为静态:
然后您将使用
Student.ExamineStudentsMembers(s1)
。使用s1.ExamineStudentsMembers(s2)
是无效的。如果这不是预期目的,我会将该方法重写为:
然后通过编写
s1.ExamineStudentsMembers()
来使用上述方法If you intend to examine a given student's information then I would change the method to be static:
You would then use
Student.ExamineStudentsMembers(s1)
. Usings1.ExamineStudentsMembers(s2)
would be invalid.If this isn't the intended purpose I would rewrite the method as:
The above would then be used by writing
s1.ExamineStudentsMembers()
私人成员将向客户隐藏实施细节。客户端应该只看到接口(公共方法/字段/属性)。
目的不是为了保护程序员免受自己的伤害。
这也不是一个安全功能,因为您始终可以通过反射访问私有字段。
真正做到了界面与界面的分离。实施(黑盒设计),以及客户根据合同进行编程(所有公共领域)。
例如,如果您有一个公共 get 属性,它可以直接访问某些私有字段,或者可以从其他一些字段计算值。
目的是,客户端只知道合约(公共财产)并且可以在不影响客户端的情况下更改实现
Private members are to hide implementation details from clients. The clients should only see the interface (public methods / fields / properties).
The purpose is not to protect the programmer from himself.
This is also NOT a security feature because you can always access private fields via reflection.
It's really to separate interface & implementation (black box design), and clients programming against a contract (all public fields).
For example if you have a public get property, it could access some private field directly, or it could calculate the value from some other fields.
The purpose is, the client only knows the contract (the public property) and the implementation can be changed without affecting the client
对象范围并不意味着安全——永远!操作系统的作用是提供运行时安全性。设计一个依赖于语言特定对象范围来限制运行时对象实例数据访问的系统是一个错误。如果情况并非如此,那么根据定义,所有非面向对象语言都是不安全的。
Object scope does not ever imply security - ever! It is role of the OS to provide runtime security. It is a bug to design a system that relies on language specific object scope to limit runtime object instance data access. If this were not the case, then all non OO languages are, by definition, not secure.