0

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

4

10 回答 10

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

您获取类型,然后使用 Instance 和 NonPublic 字段提取字段,然后设置值。

所以:

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);
于 2013-04-03T11:34:43.573 回答
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
于 2013-04-03T11:30:22.937 回答
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
于 2013-04-03T11:39:12.987 回答
0

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

于 2013-04-03T11:32:00.297 回答
0

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

于 2013-04-03T11:32:08.390 回答
0

您可以将其公开:

public int StudentId {get;set;}

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

private int StudentId;

public void ChangeStudentId(int NewStudentId)
{
    StudentId = NewStudentId;
}
于 2013-04-03T11:32:24.187 回答
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);
于 2013-04-03T11:32:35.633 回答
0

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

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

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

public int StudentId() { return this.studentId; }
于 2013-04-03T11:34:43.293 回答
0

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

FieldInfo StudentIDField= typeof(Student).GetField("StudentId",BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
StudentIDField.SetValue(1);
于 2013-04-03T11:35:04.750 回答
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;
   }
}

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

于 2013-04-03T11:35:13.073 回答