更改类的私有成员的值

时间:2013-04-03 11:28:36

标签: c#

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

10 个答案:

答案 0 :(得分:2)

简而言之:否。

In Long:取决于。

您可以通过属性公开私有字段

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);

您获得该类型,然后使用Instance和NonPublic字段拉出该字段,然后设置该值。

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);

答案 1 :(得分:1)

您可以Public类的Student属性访问私有成员的值_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

答案 2 :(得分: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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

你可以公之于众:

public int StudentId {get;set;}

或者,您可以使用单独的方法来更改它:

private int StudentId;

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

答案 6 :(得分:0)

干净的方法是将其作为公共财产或至少提供一种公共方法来改变身份。

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);

答案 7 :(得分:0)

您需要将其封装在公共方法中。最简单的方法(如果您使用的是Visual Studio Pro或更高版本)是右键单击声明它的属性,移过“Refactor”并单击“Encapsulate field”。 VS自动生成get和set修饰符。您可以删除eiter,以使属性为只读或只写。

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

如果您使用的是Visual Studio Express或其他编辑器,请执行以下操作:

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

答案 8 :(得分:0)

在这种情况下你可以使用反射:

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

答案 9 :(得分:0)

您可以通过多种方式更改它...您可以将其设为Public属性,也可以使用反射来更改它。

实际上,如果您的代码更改了StudentID并且现在它与另一个学生冲突怎么办?如果您要创建一个控制学生的课程,例如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;
   }
}

您可以在此时将Id设为内部,或使用方法尝试减少某人直接修改它的机会。