Accessing a parent instance's properties? - c#

Lets say I have a few classes that looks a bit like these:
This class I'll call the parent instance:
public class Foo : Disposable {
public Foo() {
Bars = new List<Bar>();
FullPath = string.empty;
}
public Foo(string szInfo) {
Bars = new List<Bar>();
ImportantInfo = szInfo;
}
~Foo() => this.Dispose(false);
/* IDisposible stuff cropped for simplicity */
public string ImportantInfo {get; internal set;}
public List<Bar> Bars {get; internal set;}
public void SomeContainerLoadMethod() {
/* Add some bars here */
Bars.Add( new Bar() );
Bars.Add( new Bar() );
/* etc... */
}
}
As you can see here, the parent instance Foo holds onto some Bar classes.
I'll call these Bar classes in the List<Bar> the child instance containers in this question. Here's the definition of the Bar class in the example code way:
public class Bar : Disposable {
Bar() { }
~Bar() => this.Dispose(false);
/* IDisposable stuff cropped for simplicity */
public string CoolBuff {get; internal set;}
public void SomeCoolStringBufMethod() {
/* Do something to populate CoolBuff, but I need ImportantInfo! */
}
}
How would I access ImportantInfo from the parent instance , in the child instance container's SomeCoolStringBufMethod() ?
Here are the complications to this problem:
Doing it without having to make a duplicate ImportantInfo property and pass it into the child instance container's constructor
Doing it without having to pass ImportantInfo in as an argument when the child instance's SomeCoolStringBufMethod() method is called from
the parent .
Is this possible, say with System.Reflection, to 'look up' the fact a Bar is a member of a Foo, and fetch Foo's ImportantInfo property ?

You can't.
The two options you list are really the only way to do it.
Remember that any class instance exists at an address in memory. Variables just tell your application where to look in memory for the data. So sure, you can use reflection to find the ImportantInfo property of an instance of Foo, but which instance? Where should it look for it in memory? You have to know where in memory to look.
You know where in memory to look by using a variable. So you need to pass a variable to Bar somehow.
If there was a way to use reflection to find every active instance of a class, you could use that to figure it out in a round-about way, but there is no way to do that.
A small note: when you pass a string to a method, you aren't creating a duplicate. More on that here if you're interested.

Short Answer is NO.
Long Answer is Theoretically Yes, but Practically No.
Because you Bar have no reference to Foo at all, so you can't even tell which Foo contain your Bar, you can't even tell if your Bar is referenced by any Foo at all.
In order to figure that all , you have to trace back who is referencing your Bar.
In Theory it could be done using technique like GC,but GC does reference search from Top to Bottom which means from GC root to Foo then to your Bar , is doesn't do Bottom to Top. You can build your external double linked GC like Foo,Bar Graphic.
In Practice this will take you huge amount of effort, after that, you are also facing the Challenge to manage your own GC cycle of your Foo``Bar graphic.
So Short Answer is NO.

Number two is the way to go. (And no, I'm not trying to be funny.)
...pass ImportantInfo in as an argument when the child instance's SomeCoolStringBufMethod() method is called from the parent.
Methods are how classes interact with each other. Having a reference to another object is merely a means to the end of being able to call its methods and access its properties.
There's good reasons why we don't usually create classes with circular references between them. Imagine, for example, Text.StringBuilder. What if it had a reference to the class that created it, regardless of how it obtained that reference - via the constructor, reflection, or anything else.
What would StringBuilder do with that reference? In order to do anything with that object other than call ToString() it would need to know the type of that object. But if it knows the type of that object then it implies that StringBuilder only works if it has a reference to that type of object. That means the class that depends on StringBuilder and StringBuilder can only be used in conjunction with each other.
Relating that back to your class: What does your child class need? Does Bar need a Foo? No. It needs a string. Any class that calls its method can give it a string. So why couple it to another class? One day you or someone else will need to make Bar work without a Foo and then you'll have a knot to untie.
If Bar depends on a Foo to get its ImportantProperty, that also makes unit testing very difficult. You'd have to create a Foo and then create a Bar so that the Bar can get its ImportantProperty from the Foo. If it depends on a string then it's easy to test. The test only has to create a string.
In your example, passing ImportantProperty to a Bar constructor wouldn't make sense because it's a writable property of Foo. That means Foo can change it, and then all the Bars will have a different property unless you create all new ones. (Perhaps the fact that ImportantProperty can change is the reason why you want a reference back to the parent, but passing a string to a method call still solves that problem.)
You can almost certainly make this work without the child containing its own reference to the parent. If it must have that reference then it would make sense to pass that reference to the constructor of the child.

Related

C# modification of read-only field via reference

I'm coming from C++ and I dearly miss "const" in C#.
I have tracked down a nasty bug in my code, consider this:
class MyClass {
BitArray myFlags { get; private set; } // this should not be able to be manipulated from outside
// ... constructor here creating the BitArray ...
}
// ...
MyClass foo = new MyClass();
BitArray bar = foo.myFlags;
bar.SetAll(false); // circumvents encapsulation eventually putting the class in inconsitent state
The user can without any problems, even unintendedly change the state of my object.
How do I expose members of a class safely, without giving the user the chance to manipulate the state of my object? Do I have to ".clone()" every single reference-based member (so basically everything) when providing a public (read) access to this member?
What I want to achieve is proper encapsulation. When a user creates an instance of my class, and reads a member, I want the member to be protected against writing, unless it also has a public setter.
C# offers ReadOnlyCollection as option for immutable collection.
Hope it helps!

C#, making public members their methods private

I the following class:
public class Humptydump
{
public Humptydump()
{ }
public Rectangle Rectangle { public get; private set; }
}
in this class the Rectangle class comes from system.drawing,
how do i make it so people cannot access the methods of the rectangle, but can get the rectangle itself?
In your case, it will "just work".
Since Rectangle is a struct, your property will return a copy of the Rectangle. As such, it will be impossible for anybody to modify your Rectangle directly unless you expose methods to allow this.
That being said, it's impossible, in general, to provide access to a type without also providing access to methods defined on the type. The methods go along with the type. The only alternative in those cases would be to create a new type that exposed the data you choose without the data or methods you wish to be exposed, and provide access to that.
If rectangle was not a struct, one possible thing would be deriving it and hiding those methods:
public class DerivedClass : BaseClass
{
new private SomeReturnType SomeMethodFromBaseClasse(SameParametersAsInBaseClassAndSameSignature
{
//this simply hides the method from the user
//but user will still have the chance to cast to the BaseClass and
//access the methods from there
}
}
Are you talking about the Rectangle object specifically, or on a more general term and just using that as an example?
If you're talking on a more general term, this is something that comes up very often in refactoring patterns. This most commonly happens with collections on objects. If you expose, for example, a List<T> then even if the setter is private then people can still modify the collection through the getter, since they're not actually setting the collection when they do so.
To address this, consider the Law of Demeter. That is, when someone is interacting with a collection exposed by an object, should they really be interacting with the object itself? If so, then the collection shouldn't be exposed and instead the object should expose the functionality it needs to.
So, again in the case of a collection, you might end up with something like this:
class SomeObject
{
private List<AnotherObject> Things;
public void AddAnotherObject(AnotherObject obj)
{
// Add it to the list
}
public void RemoveAnotherObject(AnotherObject obj)
{
// Remove it from the list
}
}
Of course, you may also want to expose some copy of the object itself for people to read, but not modify. For a collection I might do something like this:
public IEnumerable<AnotherObject> TheObjects
{
get { return Things; }
}
That way anybody can see the current state of the objects and enumerate over them, but they can't actually modify it. Not because it doesn't have a setter, but because the IEnumerable<T> interface doesn't have options to modify the enumeration. Only to enumerate over it.
For your case with Rectangle (or something similar which isn't already a struct that's passed by value anyway), you would do something very similar. Store a private object and provide public functionality to modify it through the class itself (since what we're talking about is that the class needs to know when its members are modified) as well as functionality to inspect it without being able to modify what's being inspected. Something like this, perhaps:
class SomeObject
{
private AnotherObject Thing;
public AnotherObject TheThing
{
get { return Thing.Copy(); }
}
public void RenameThing(string name)
{
Thing.Name = name;
}
// etc.
}
In this case, without going into too much detail about what AnotherObject is (so consider this in some ways pseudo-code), the property to inspect the inner object returns a copy of it, not the actual reference to the actual object. For value types, this is the default behavior of the language. For reference types, you may need to strike a balance between this and performance (if creating a copy is a heavy operation).
In this case you'll also want to be careful of making the interface of your object unintuitive. Consuming code might expect to be able to modify the inner object being inspected, since it exposes functionality to modify itself. And, indeed, they can modify the copy that they have. How you address this depends heavily on the conceptual nature of the objects and how they relate to one another, which a contrived example doesn't really convey. You might create a custom DTO (even a struct) which returns only the observable properties of the inner object, making it more obvious that it's a copy and not the original. You might just say that it's a copy in the intellisense comments. You might make separate properties to return individual data elements of the inner object instead of a single property to return the object itself. There are plenty of options, it's up to you to determine what makes the most sense for your objects.

Is there a way to construct child object from parent reference?

Consider I have 2 classes:
public class ComplicatedParent
{
// Lots of data
}
public class SimpleChild : ComplicatedParent
{
public string SomeAdditionalData { get; set; }
public SimpleChild(string arg) : base()
{
SomeAdditionalData = arg;
}
}
And SomeFunction that returns instance of ComplicatedParent. Is there a simple way to construct child from parent's reference, preserving parent's state?
Actually ComplicatedParent class and SomeFunction are third party so I can't change them.
You can't do this automatically in the language. You can do it with Automaper or by manual assignments.
The best way to do this would be to write a constructor for SimpleChild that takes an instance of ComplicatedParent as an argument. The constructor would then copy the data across. You could try using clone() to create a copy of the ComplicatedParent, cast it to a SimpleChild, add the additional data and return it.
For help on cloning you might want to have a gander at this link:
Deep cloning objects
If by "preserving parent state" you mean preserving let's say internal values of the parent class, you can not do that, you should implement it by yourself. Something like:
public static SimpleChildFromParent(ComplicatedParent cp); // static method in SimpleChild class.
//and somewhere in the code
SimpleChild sc = SimpleChild.SimpleChildFromParent(cp); // where cp is ComplicatedParent previously created and intialized.
Regards.
If you can override the properties of your parent, You can take the parent object in the child constructor and delegate the calls to the internal referenced parent. This is only possible if the parent properties are virtual.
If ComplicatedParent really is that complex you should consider splitting it into smaller classes and store instances to these in ComplicatedParent (aggregation, not inheritance). If these objects are immutable, implementing the construct-from-prototype should be easy.
As of the construction of the objects, consider the Prototype pattern.

C# constructor design

I have a class which you pass in a folder and then it goes off and processes a lot of data within the specified folder.
For instance:
MyClass myClass = new MyClass(#"C:\temp");
Now it goes off and reads say a couple of thousand files and populates the class with data.
Should I move this data out from the constructor and have it as a separate method, such as the following?
MyClass myClass = new MyClass();
myClass.LoadFromDirectory(#"C:\temp");
Maybe you should try it this way with a static method that returns an instance of the object.
var myClass = MyClass.LoadFromDirectory(#"C:\temp");
This will keep the initialization code outside of your constructor, as well as giving you that "one line" declaration you are looking for.
Going on the comment from below from the poster, by adding State an implementation could be like so:
public class MyClass
{
#region Constructors
public MyClass(string directory)
{
this.Directory = directory;
}
#endregion
#region Properties
public MyClassState State {get;private set;}
private string _directory;
public string Directory
{
get { return _directory;}
private set
{
_directory = value;
if (string.IsNullOrEmpty(value))
this.State = MyClassState.Unknown;
else
this.State = MyClassState.Initialized;
}
}
#endregion
public void LoadFromDirectory()
{
if (this.State != MyClassState.Initialized || this.State != MyClassState.Loaded)
throw new InvalidStateException();
// Do loading
this.State = MyClassState.Loaded;
}
}
public class InvalidStateException : Exception {}
public enum MyClassState
{
Unknown,
Initialized,
Loaded
}
It depends. You should evaluate the basic purpose of the class. What function does it perform?
What I usually prefer is to have a class constructor do the initialization necessary for the functioning of the class. Then I call methods on the class which can safely assume that the necessary initialization has been done.
Typically, the initalization phase should not be too intensive. An alternative way of doing the above may be:
// Instantiate the class and get ready to load data from files.
MyClass myClass = new MyClass(#"C:\temp");
// Parse the file collection and load necessary data.
myClass.PopulateData();
I agree with Ari and others - split them up.
A constructor should really do the minimum amount of work (simply initialise the object ready for use and leave it at that). By using a separate method to do the work:
It is clearer to the caller that the worker function may take a long time.
It is easy to provide several constructors to initialise the object with different information (e.g. you might be able to pass in your own class (rather than a string) that can supply the pathname. Or you could pass in an extra parameter that specifies a wildcarded filename to match, or a flag to specify if the search should recurse into subfolders).
You avoid any issues with the constructor. In the constructor the object is not fully formed, so it can be dangerous to do work - e.g. calling a virtual function inside a constructor is a very bad idea. The less code you put in the constructor the less likely it is that you'll do something "bad" by accident.
It's cleaner coding style to separate different behaviours/functions into separate methods. Keep initialisation and work separated
A split class will be easier to maintain and refactor in future.
Is this all your class does? If so, then I would say it doesn't really matter. But it is likely that you're class is actually doing more than what you have shown. Does it have any error handling, for example?
The purpose of the constructor is to construct an object. The purpose of a method is to perform an action. So my vote is for this form:
MyClass myClass = new MyClass();
myClass.LoadFromDirectory(#"C:\temp");
I think you should decide between the two approaches above ("first initialize, then execute" vs "empty init, perform with params") based on whether you plan on reusing the same object to perform the same operation on a differnt input.
if the class is only used to run the task on a fixed param, I'd go with initializing it in the constructor (making it readonly even), and then performing the task on a different method.
If you want to keep performing the the task on different params, I'd put it in the task method itself.
If all the class does is this task, I'd also consider changing it all to a static class/methods - it doesn't need to keep its internal state.
Anyway, I would never put the task itself in the constructor. As Cerebrus said, the initialization should be fast.
Unless the main purpose of your class is to perform I/O, you should probably not be performing I/O (potentially throwing an IOException) in the constructor.
Consider splitting the class in two:
interface IMyDataSource
{
// ...
}
class FileDataSource: IMyDataSource
{
public FileDataSource(string path)
{
// ...
}
}
class MyClass
{
public MyClass(IMyDataSource source)
{
// ...
}
}
IMyDataSource myDS = new FileDataSource(#"C:\temp");
MyClass myClass = new MyClass(myDS);
That way the main class can focus on managing its own state, while the data source builds the initial state from the file contents.
If that is the only resource the class works with, it'd probably be better to pass the path to the constructor. Otherwise, it would be a parameter to your class members.
My personal preference would be to use C# 3.0 initializers.
class MyClass {
public string directory;
public void Load() {
// Load files from the current directory
}
}
MyClass myClass = new MyClass{ directory = #"C:\temp" };
myClass.Load();
This has a few advantages:
Object instantiation won't have an
automatic file system side effect.
All arguments are named.
All arguments are optional (but,
of course, could throw an
exception in Load() if not defined)
You can initialize as many properties as you
want in the instantiation call
without having to overload the
constructor. For instance, options
for whether to recurse directories,
or a wildcard for filespec to search
for.
You could still have some logic
in the setter for directory to do
some stuff, but again, side effects
are usually not a good thing.
By performing file operations in a
separate procedure call, you avoid
the issue of not being able to
reference your myClass instance in
the exception handler.
I'm going to echo the "split them up" folks here. If it helps, try this:
Ask yourself, "What does this method/property/field do?"
Make it do that; no more, no less.
Applying that here, you get this:
The constructor is supposed to create the object.
Your method is supposed to load its data from the filesystem.
That seems to me to be a lot more logical than "The constructor is supposed to create the object and load its data from the filesystem.

Best practice when assigning a collection reference to a property

I'm heavily geared towards C++ thinking and need some guidance on a specific C# matter. Let's assume we have the following class:
public class Foo
{
private IList<Bar> _bars = new List<Bar>(); // Note IList<> vs List<>.
public IList<Bar> Bars
{
get { return _bars; }
set
{
...
}
}
}
Now, in place of the ..., I'm leaning towards clearing _bars and AddRange the items from the set argument value, instead of just assigning value to _bars. The way I see it, is that I want to keep referencing the same items that the value items references, not the actual IList<Bar> that value references.
Is that wrong thinking on my side? How do you think here?
Edit: After some comments, I realized I must add that I want to be able to use an existing collection of Bars in the Foo ctor and initialize _bars from that collection. So, with that revision and the comments so far, this feels better:
public class Foo
{
private readonly List<Bar> _bars = new List<Bar>();
public Foo(IEnumerable<Bar> bars)
{
_bars.AddRange(bars);
}
public IList<Bar> Bars
{
get { return _bars; }
}
}
Is it better?
If we're talking about business (domain) objects, I expose IEnumerable<T> and whatever methods are appropriate for the collection, typically Add, Remove, and Clear. I almost never expose a setter for a collection.
Is it necessary to be able to make the Bars property of your instance of Foo refer to another List ?
If not, then I would prefer not to have a property-setter for Bars.
If it is necessary to be able to set the Bars property to another List instance, then I think I would find it strange to find that your setter modifies the list.
I mean: when I assign another List of Bars to that property, I would assume that my instance of Foo then contains the Bars that were available in the list that I've assigned to that property. No more, no less.
I would find it strange to find out that suddenly the collection contains more (or less) Bars...
Based on inferred requirements from your question:
public class Foo
{
private readonly IList<Bar> _bars = new List<Bar>();
public IList<Bar> Bars
{
get { return _bars; }
}
}
Absolutely, there is no need to expose a setter for the Bars property. Internally you hold a reference to the collection, which as Kent suggests could be marked as Readonly. Through the getter the caller can do what they want with the collection with the methods available (Add, Remove, Clear, AddRange, etc), but crucially they can never change the internal reference you hold to the collection object.
This then allows you to control what methods are allowed. As Jamie suggests, having the property return type IEnumerable would result in the Bars property exposing a readonly collection. Exposing IList means the contents of the collection could be modified. A setter on the property would leave it wide open for the caller to do what they want and you are no longer in control.
Edit
Following the question edit above. It really depends on how the Foo object will be used.
Since your main concern is to initialise Foo from an existing list of Bar objects...
IList<Bar> bars = ...some list of Bars previously constructed...
Your latest code example for Foo forces the caller to initialise via the constructor but then also allows them to change the collection via the property
Foo foo = new Foo(bars);
...
foo.Bars.Clear();
foo.Bars.AddRange(bars);
When allowing an object to be initialised via the constructor you need to ask yourself why you are doing this. Is it...
for the caller's convenience? To allow the calling code to supply values that can be subsequently changed via properties.
because you want to restrict how the object is used? Forcing values (or certain combinations of values) to be set on object construction and remain fixed throughout the lifetime of the object.
You need to ask yourself – Do you want the caller to be able to change the contents of the Bars collection after the Foo object has been constructed?
If No – Make the Bars property expose a read only collection.
If Yes – Add a default constructor to the Foo object so that the caller doesn’t have to supply a list to initialise it. But they will have the option to do so if they so choose via the overloaded constructor.
I'm ok with setters for such properties, but I usually disallow nulls because null rarely has different business meaning than an empty list.
set { _bars = value ?? new List<Bar>();}
I think returning the _bars reference from the getter is a bit dodgy. Do you really want clients of the class being able to modify the contents of the list?
So I would do the following: make a copy on construction/setting and return a readonly view for the getter.

Categories