tags:

views:

172

answers:

6

I've got a base class from an outside library that I can't modify - here's the relevant piece:

public class BaseClass
{
     List<string> _values;
     public Values { get { return _values; } }
}

I am inheriting the BaseClass, and I want to set _values to a class that inherits from List(T) in the constructor:

public InheritingClass : BaseClass
{
     public InheritingClass():base()
     {
          //set base._values = new InhertingList<string>(); ?
     }
}

What's the best way to set base._values there? Is there a way to find what private variable is fetched by Values and set that in case the private variable is renamed in the future?

There are other ways I can accomplish what I need to do, but if I could do the following, it would be quicker by far than any ways of achieving my goal without setting the private property value.

A: 

No, there is no way to do what you're looking for. Private variables are meant to be private - namely, they can't be seen or altered by any code.

Jon Benedicto
+3  A: 

Keeping it private, by definition, is meant to prevent this exact scenario.

The best option would be to implement a protected setter:

public class BaseClass
{
     public Values { 
        get { return _values; }
        protected set { _values = value; }
     }
}

This way, your InheritingClass has access to the setter, and can do:

this.Values = new InhertingList<string>();

But since you can't change the base class, it is, technically, possible to do this via reflection (in a full trust scenario). I don't recommend this approach, though:

FieldInfo field = typeof(BaseClass).GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic );
field.SetValue(this, this.Values = new InhertingList<string>() );

The danger of doing what you are attempting, btw, is that you're going to change the implementation defined by the BaseClass to something that you're providing. It's very easy to introduce subtle bugs, since you're (purposefully) "breaking" the implementation details in the base class.

I'd try to rethink your algorithm, and see if there's another way around this issue.

Reed Copsey
he can't modify the base class
AdamRalph
I know - I added the reflection sample showing how it is technically possible to do this, too...
Reed Copsey
This works but only if you know the name of the private field - which I'm not sure the he does.
ShdNx
Yeah - which leaves you with using Reflector to get it, or GetFields and guessing...
Reed Copsey
I do know the name of the private field, though I'd like to not make that assumption. I'd rather base it on what the public get accessor references, but it doesn't look like that's possible.
jball
As an aside, is it really dangerous if the class I'm setting the private variable to is a sub-class of what the private variable and public accessor are?
jball
Technically, it should be reasonable due to the Liskov Substitution Principal - but... if the base class were to use it's own subclass of List<T>, and you used a different subclass, it could be very bad.
Reed Copsey
The base class, technically, is free to use any subclass of List<T> in its definition, not just List<T> directly. If it depended on custom behavior, overwriting with your implemnetation could break it badly.
Reed Copsey
That makes sense, thanks Reed.
jball
+2  A: 

If you really need to set the value, you can use reflection. But that's no good coding style and may be slow.

Edit: It might be possible to disassemble your BaseClass and change its implementation. Bun then you might have to disassemble the whole library.

Perhaps you can provide some more details on your problem?

Simon Ottenhaus
A: 

Normally, when fields don't have mutator methods, you'd use the constructor of the class to instantiate the object (and it's relevant fields).

BaseClass base = new BaseClass(List<string> yourList);
mheathershaw
BaseClass only has a zero argument contructor.
jball
+1  A: 

Usually, when you don't have a property with an accessible setter provided for a field, it means that you should not modify that field from anywhere but the BaseClass - if the creator of the BaseClass class would have wanted you to be able to modify that field, he'd have exposed a property with a protected setter or something like that. So generally it's not recommended to hack it.

You could certainly do it by reflection though, providing you know the name of the private field - I don't think it is possible to extract the body of the property.

As for the other answers: he wrote "I've got a base class from an outside library that I can't modify".

ShdNx
+1  A: 

You can't set the private property. You will either have to inherit from another base class or create your own base class that provides the behaviour.

Of course, depending on the level of trust your application is running under, you may be able to set the private variable via reflection but that would really be a hack to get around what is actual a problem in the design.

AdamRalph