2013-04-03 51 views
0

假设我有一个班级Student并且它包含一个私人成员StudentID。现在我在另一个类中创建一个Student类的对象,并且我的要求是更改StudentID的值。是否可以访问StudentID并更改其值?更改某个班级的私人成员的值

+0

您可以访问只有来自外部的公众成员。所以你需要一些公开的东西来改变这个价值(可能会进行验证)或者公开你的成员。这取决于你的架构。 – JleruOHeP

回答

1

你可以使用反射来改变私人成员,但这可能不是你正在寻找的。

如果你不想让公众成员,你可以改变它的公共方法:

public class Student { 

    private int StudentID; 

    public void SetStudentId(int id) { 
    StudentID = id; 
    } 

} 

如果您不希望公众方法方便,则可以将界面为它,并具体实现接口。这样的方法是仅当你有接口,而不是类型的参考,当你有这个类的类型的引用:

public interface IChangeId { 
    public void SetStudentId(int id); 
} 

public class Student : IChangeId { 

    private int StudentID; 

    void IChangeId.SetStudentId(int id) { 
    StudentID = id; 
    } 

} 

例子:

Student john = new Student(); 

john.SetStudentId(42); // not allowed 

IChangeId johnSetId = john; 

johnSetId.SetStudentId(42); // allowed 
+0

+1用于显式接口实现。 – Oliver

+0

虽然这会起作用,但我认为只是介绍接口来获取被认为是隐藏字段的接口有点臭,如果接口是供内部使用的,那么它可能在一定程度上可以接受。 – Clint

+0

@ Clint:是的,但不会像使用反射一样臭...;) – Guffa

1

您可以StudentPublic财产访问私有成员_StudentId

public class Student 
{ 
    private int _StudentId; 

    public int StudentId 
    { 
     get 
     { 
      return _StudentId; 
     } 
     set 
     { 
      _StudentId = value; 
     } 
    } 
} 

的价值现在你可以使用它像这样

Student objStudent = new Student(); 
    objStudent.StudentId = 5; // your Id 
+0

我没有得到它......你可以通过写一个示例代码来解释吗? – user2091061

+0

我已经更新了我的答案,以显示如何使用此属性 – Sachin

0

你就是不行。您需要拥有访问学生ID私人成员的公共属性,或者您可以使用某些公共方法访问它。

0

也许在构造函数中传递ID值是有意义的,所以我会添加另一个接受StudentID的值的构造函数。

0

你可以把它公开:

public int StudentId {get;set;} 

或者,你可以做一个单独的方法来改变它:

private int StudentId; 

public void ChangeStudentId(int NewStudentId) 
{ 
    StudentId = NewStudentId; 
} 
0

清洁方式是使其成为公共财产或者至少提供一个公共方法来改变id。

public StudentID {get; set;} 

// or 
public StudentID {get; private set;} 
public ChangeStudentID(int newID); 

肮脏的方法是反思:

var instance = new Student(); 
var type = instance.GetType(); 
var propInfo = type.GetProperty("StudentID", BindingFlags.Instance | BindingFlags.NonPublic); 
propInfo.SetValue(instance, 14, null); 
+0

试图使用反射来更改它,但它显示了一个例外 – user2091061

+0

@ user2091061:它是实现私有setter还是只是一个getter属性?也许你必须通过使用'GetField'和适当的后台字段来直接更改后台字段? – Oliver

0

你需要它封装在一个公共的方法。最简单的方法(如果您使用Visual Studio Pro或更高版本)右键单击声明的属性,移动“重构”并单击“封装字段”。 VS自动获取并设置修改器。您可以删除eiter以使属性为只读或只写。

如果该属性被声明为“int studentId”,则生成的封装将位于“Student.StudentId”(注意大写字母)。如果该属性被声明为“int StudentId”,则据我所知,封装将默认为“Student.StudentId_1”。您可以在创作过程中选择自己的名字。

如果您使用的Visual Studio Express或其他编辑器,只是这样做:

public int StudentId() { return this.studentId; } 
2

总之:第

在长:依赖。

您可以通过属性

private int _studentID; 
public int StudentID 
{ 
    get { return _studentID; } 
    set { _studentID = value; } 
} 

但不知何故,我不认为这是你以后暴露私有字段。

私人领域是私人的有原因如果你不希望它是私人的,那么没有它私人或通过一个属性如上所示公开它。

如果你真的需要访问私有字段并将其值设置,那么你可以采取反射路线:

var a = new abc(); 
a.GetType().GetField("x", 
    System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(a, 12); 

你得到那么该类型使用则只需设置实例和非公共领域拉出场价值。

SO:

public sealed class SomeClass 
{ 
    private int _studentID = 0; 

    public int StudentID 
    { 
     get 
     { 
      return _studentID; 
     } 

     set 
     { 
      _studentID = value; 
     } 
    } 
} 

将是“正确”的方式,但使用反射,你可以只是做

var someclass = new SomeClass(); 
     someclass.GetType() 
      .GetField("_studentID", 
       System.Reflection.BindingFlags.NonPublic | 
       System.Reflection.BindingFlags.Instance) 
      .SetValue(someclass, 12); 

如果你想使用反射,那么你可以使用扩展方法帮助:

public static class FieldExtensions 
{ 
    public static void SetPrivateField<T>(this T instance, string field, object value) 
    { 
     typeof(T).GetField(field, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) 
      .SetValue(instance, value); 
    } 
} 

然后使用该扩展方法,您可以在任何对象上设置任何专用字段!

var someclass = new SomeClass(); 
someclass.SetPrivateField("_studentID", 12); 
0

您可能会在这种情况下,使用反射:

FieldInfo StudentIDField= typeof(Student).GetField("StudentId",BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 
StudentIDField.SetValue(1); 
0

你可以在许多方面...你可以使它成为一个Public属性来改变它,而不是或者你可以使用反射来改变它。

实际上,如果您的代码要更改StudentID并且现在与另一个Student发生冲突呢?如果你要创建一个控制学生例如StudentCollection一类这个类可以再有一个ChangeId类似如下:

public class StudentCollection : List<Student> 
{ 
    public void ChangeId(Student student, int newId) 
    { 
     if(students.Where(s => s.Id == newId).Count() > 0) 
     throw new ArgumentException("A student already has that Id"); 

     student.Id = newId; 
    } 
} 

你可以在这一点上做标识内部,或使用的方法来试图减少有人直接修改它的机会。