user2091061
user2091061

Reputation: 877

Change value of a private member of a class

Suppose I have a class Student and it contains a private member StudentID. Now I make an object of Student class in some another class and my requirement is to to change the value of StudentID. Is it possible to access StudentID and change its value?

Upvotes: 0

Views: 1810

Answers (10)

Clint
Clint

Reputation: 6220

In short: No.

In Long: Depends.

You can expose the private field via a property

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

But somehow I don't think that's what you're after.

Private fields are private for a reason if you don't want it to be private then don't have it private, or expose it via a property as shown above.

If you really need to access a private field and set its value then you can take the reflection route:

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

You get the type then pull out the field using the Instance and NonPublic fields then just set the value.

SO:

public sealed class SomeClass
{
    private int _studentID = 0;

    public int StudentID
    {
        get
        {
            return _studentID;
        }

        set
        {
            _studentID = value;
        }
    }
}

Would be the "right" way, but using reflection you could just do

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

If you want to use reflection then you could use an extension method helper:

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

Then using that extension method you can set any private field on any object!

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

Upvotes: 2

Guffa
Guffa

Reputation: 700800

You could use reflection to change the private member, but that's probably not what you are looking for.

If you don't want to make the member public, you can make a public method that changes it:

public class Student {

  private int StudentID;

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

}

If you don't want the public method easily accessible, you can make an interface for it, and implement the interface specifically. That way the method is only available when you have a reference of the type of the interface, not when you have a reference of the type of the class:

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

public class Student : IChangeId {

  private int StudentID;

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

}

Example:

Student john = new Student();

john.SetStudentId(42); // not allowed

IChangeId johnSetId = john;

johnSetId.SetStudentId(42); // allowed

Upvotes: 1

Sachin
Sachin

Reputation: 40990

You can make Public property of Student class which access the value of private member _StudentId

public class Student
{
    private int _StudentId;

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

Now you can use it like this

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

Upvotes: 1

Ian
Ian

Reputation: 34549

You could change it in a number of ways... you could make it a Public property instead or you could use reflection to change it.

In reality, what if your code were to change the StudentID and now it conflicts with another Student? If you were to create a class that controls the students for example a StudentCollection this class could then have a ChangeId like the following:

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

You could at that point make the Id internal, or use methods to try and reduce the chance of someone directly modifying it directly.

Upvotes: 0

Babak
Babak

Reputation: 121

You may use Reflection in this case:

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

Upvotes: 0

Daniel
Daniel

Reputation: 813

You need to encapsulate it in a public method. Easiest way (if you're using Visual Studio Pro or above) is to right-click the property where it is declared, move over "Refactor" and click "Encapsulate field". VS automatically makes get and set modifiers. You may remove eiter in order to make the property read-only or write-only.

If the property is declared as "int studentId", the resulting encapsulation will be at "Student.StudentId" (notice the capital letter). If the property is declared as "int StudentId", the encapsulation will default to "Student.StudentId_1" as far as I remember. You may choose your own name during creation.

If you're using Visual Studio Express or another editor, just do this:

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

Upvotes: 0

Oliver
Oliver

Reputation: 45119

The clean way would be to make it a public property or at least provide a public method to change the id.

public StudentID {get; set;}

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

The dirty way would be reflection:

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

Upvotes: 0

CorrugatedAir
CorrugatedAir

Reputation: 819

You could make it public:

public int StudentId {get;set;}

Alternatively, you can make a separate method to change it:

private int StudentId;

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

Upvotes: 0

Alex Tsvetkov
Alex Tsvetkov

Reputation: 1659

Perhaps it make sense to pass ID value in a constructor, so I would add another constructor accepting some value for StudentID.

Upvotes: 0

Prasanna
Prasanna

Reputation: 760

No you can't. You need to either have a public property that accesses student ID private member or you can access it using some public methods.

Upvotes: 0

Related Questions