I'm a relative newbie to C#, although I am a competent programmer, and I confess that I am totally confused as to whether or not it is a good idea to write custom collection classes. So many people seem to say "don't", yet there is a whole set of base classes for it in C#.
Here is my specific case. I have a timetable application. As part of that, I have a service class, and the service class contains collections of things service-y, such as route links. A route link is itself a custom class:
public class Service
{
public RouteLinks RL; // A collection of RouteLink types
...
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
public Tracks RouteTrack; // Another collection, this time of Track types
}
So far I have looked at using Dictionary as the type for RouteLinks, because I need to be able to reference them. This is fine in principle. However, the process of adding a RouteLink to the RouteLinks collection involves checking to see whether it is already there, or whether it extends and existing route link, or... And for that, I need a custom Add function.
So why is is such bad practice to create custom collection classes? Why shouldn't I just inherit CollectionBase or DictionaryBase?
I should perhaps add that I am transferring this code from VBA [please don't shoot me :)] and there I HAD to implement custom collections.
Instead of having RouteLinks be a collection type, an easy solution would be to just define another class, let's say RouteLinksRepository. This class will contain a List<RouteLink> and the AddRoute(RouteLink) functionality as well as any other custom logic for interacting with this collection of RouteLink objects. Your service class will then just contain an instance of this repository class.
public class Service
{
public RouteLinksRepository RL; // A collection of RouteLink types
// ...
}
public class RouteLinksRepository
{
public List<RouteLink> RouteLinks;
public bool AddRoute(RouteLink linkToAdd)
{
//Custom logic on whether or not to add link
}
//Your other logic for the class
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
public Tracks RouteTrack; // Another collection, this time of Track types
}
If the only need is to check on double entries, a HashSet will do (implement a GetHash and Equals). However I guess you are trying to save a route. A route has a order, which means you have a order and List<> garantees the order. Make the collection objects private to hide the implementation.
public class Service
{
private List<RouteLink> RL; // A collection of RouteLink types
...
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
private List<Track> Tracks; // Another collection, this time of Track types
}
Related
'm trying to design a system where a class would be defined in a project, be referenced in another and have new functionalities in the latter. Is there a pattern for this?
Context: I have a game that has items in a common project. Both the server and client reference this same project so I can have the item StaffItem in both the server and client, making it easier to serialize and deserialize between the two. The problem is, I can't redefine the StaffItem class in the client, since it will change the server's perspective of this class. I'm trying to find a nice way to add, for instance, the rendering to the client-side view of the class (added code for textures and all that).
I'm almost at the point of giving up and simply putting the rendering code in the common project, and stubbing it for the server. Any pointers (hehe) would be appreciated.
Instead of transferring the actual objects over the wire, you could introduce a DTO class for serializing and deserializing. This decouples the actual implementations on both sides.
If I understand your question right, there are two options you may consider. First one is to use smth similar with decorator pattern:
class StaffItem : IStaffItem {
public int MyProp {get;set;}
public void MyAction() {}
}
class ClientStaffItem : IStaffItem {
private StaffItem _staffItem;
public ClientStaffItem(StaffItem staffItem) {
_staffItem = staffItem;
}
public int MyProp {
get { return _staffItem.MyProp;}
set {_staffItem.MyProp; = value;}
}
public void MyAction() {
_staffItem.MyAction();
}
public void YouClientMethod() {}
}
The other one use inheritance, but determine which fields you need to serialize and how and use attributes or custom serialization settings to mark only properties you need.
Previous Post removed; Updated:
So I have a unique issue, which is possibly fairly common though. Properties are quite possibly are most commonly used code; as it requires our data to keep a constant value storage. So I thought how could I implement this; then I thought about how easy Generics can make life. Unfortunately we can't just use a Property in a Generic without some heavy legwork. So here was my solution / problem; as I'm not sure it is the best method- That is why I was seeking review from my peers.
Keep in mind the application will be massive; this is a very simple example.
Abstract:
Presentation Layer: The interface will have a series of fields; or even data to go across the wire through a web-service to our database.
// Interface:
public interface IHolder<T>
{
void objDetail(List<T> obj);
}
So my initial thought was an interface that will allow me to Generically handle each one of my objects.
// User Interface:
public class UI : IHolder
{
void objDetail(List<object> obj)
{
// Create an Instance
List<object> l = new List<object>();
// Add UI Fields:
l.Add(Guid.NewGuid());
l.Add(txtFirst.Text);
l.Add(txtLast.Text);
// l to our obj
obj = l;
return;
}
}
Now I have an interface; which has been used by our UI to put information in. Now; this is where the root of my curiosity has been thrown into the mixture.
// Create an Object Class
public class Customer : IHolder
{
// Member Variable:
private Guid _Id;
private String _First;
private String _Last;
public Guid Id
{
get { return _Id; }
set { _Id = value; }
}
public String First
{
get { return _First; }
set { _First = value; }
}
public String Last
{
get { return _Last; }
set { _Last = value; }
}
public virtual objDetail(List<Customer> obj)
{
// Enumerate through List; and assign to Properties.
}
}
Now this is where I thought it would be cool; if I could use Polymorphism to use the same interface; but Override it to do the method differently. So the Interface utilizes a Generic; with the ability to Morph to our given Object Class.
Now our Object Classes; can move toward our Entity interface which will handle basic Crud Operation.
I know this example isn't the best for my intention; as you really don't need to use Polymorphism. But, this is the overall idea / goal...
Interface to Store Presentation Layer UI Field Value
Implement the Properties to a Desired Class
Create a Wrapper Around my Class; which can be Polymorphed.
Morphed to a Generic for Crud Operation
Am I on the right path; is this taboo? Should I not do this? My application needs to hold each instance; but I need the flexibility to adapt very quickly without breaking every single instance in the process. That was how I thought I could solve the issue. Any thoughts? Suggestions? Am I missing a concept here? Or am I over-thinking? Did I miss the boat and implement my idea completely wrong? That is where I'm lost...
After pondering on this scenario a bit, I thought what would provide that flexibility while still ensuring the code is optimized for modification and business. I'm not sure this is the right solution, but it appears to work. Not only does it work, it works nicely. It appears to be fairly robust.
When is this approach useful? Well, when you intend to decouple your User Interface from your Logic. I'll gradually build each aspect so you can see the entire structure.
public interface IObjContainer<T>
{
void container(List<T> object);
}
This particular structure will be important. As it will store all of the desired content into it.
So to start you would create a Form with a series of Fields.
Personal Information
Address Information
Payment Information
Order Information
So as you can see all of these can be separate Database Tables, but belong to a similar Entity Model you are manipulating. This is quite common.
So a Segregation Of Concern will start to show slightly, the fields will be manipulated and passed through an Interface.
public interface IPersonalInformation
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
So essentially the Interface is passing its variable, to the Interface. So you would culminate an interface to handle that entire form or individual interfaces that you wish to call so that they remain reusable.
So now you have a series of Interfaces, or a single once. But it contains all these variables to use. So you would now create a class:
public class CustomerProperties: IPersonalInformation, IOrderInformation
{
// Implement each Interface Property
}
Now you've created a container that will hold all of your values. What is nifty about this container is you can reuse the same values for another class in your application or choose different ones. But it will logically separate the User Interface.
So essentially this is acting similar to a Repository.
Now you can take these values and perform the desired logic. What becomes wonderful now, is after you've performed your logic you pass the object into our Generic List. Then you simply implement that method in another class for your goal and iterate through your list.
The honesty is it appears to work well and decouple nicely. I feel that it was a lot of work to do something similar to a normal Repository and Unit Of Work, this answers the question but weather or not it is ideal for your project I would look into Repository, Unit Of Work, Segregation Of Concern, Inversion Of Control, and Dependency Injection. They may do this same approach cleaner.
Update:
I thought about it after I wrote this up, I noticed you could actually implement those property values into the Generic List structure bypassing a series of interfaces; but that would introduce consistency issues as you'd have to be aware of what data is being passed in each time, in order. It's possible, but may not be ideal.
I have a class that upon construction, loads it's info from a database. The info is all modifiable, and then the developer can call Save() on it to make it Save that information back to the database.
I am also creating a class that will load from the database, but won't allow any updates to it. (a read only version.) My question is, should I make a separate class and inherit, or should I just update the existing object to take a readonly parameter in the constructor, or should I make a separate class entirely?
The existing class is already used in many places in the code.
Thanks.
Update:
Firstly, there's a lot of great answers here. It would be hard to accept just one. Thanks everyone.
The main problems it seems are:
Meeting expectations based on class names and inheritance structures.
Preventing unnecessary duplicate code
There seems to be a big difference between Readable and ReadOnly. A Readonly class should probably not be inherited. But a Readable class suggests that it might also gain writeability at some point.
So after much thought, here's what I'm thinking:
public class PersonTestClass
{
public static void Test()
{
ModifiablePerson mp = new ModifiablePerson();
mp.SetName("value");
ReadOnlyPerson rop = new ReadOnlyPerson();
rop.GetName();
//ReadOnlyPerson ropFmp = (ReadOnlyPerson)mp; // not allowed.
ReadOnlyPerson ropFmp = (ReadOnlyPerson)(ReadablePerson)mp;
// above is allowed at compile time (bad), not at runtime (good).
ReadablePerson rp = mp;
}
}
public class ReadablePerson
{
protected string name;
public string GetName()
{
return name;
}
}
public sealed class ReadOnlyPerson : ReadablePerson
{
}
public class ModifiablePerson : ReadablePerson
{
public void SetName(string value)
{
name = value;
}
}
Unfortunately, I don't yet know how to do this with properties (see StriplingWarrior's answer for this done with properties), but I have a feeling it will involve the protected keyword and asymmetric property access modifiers.
Also, fortunately for me, the data that is loaded from the database does not have to be turned into reference objects, rather they are simple types. This means I don't really have to worry about people modifying the members of the ReadOnlyPerson object.
Update 2:
Note, as StriplingWarrior has suggested, downcasting can lead to problems, but this is generally true as casting a Monkey to and Animal back down to a Dog can be bad. However, it seems that even though the casting is allowed at compile time, it is not actually allowed at runtime.
A wrapper class may also do the trick, but I like this better because it avoids the problem of having to deep copy the passed in object / allow the passed in object to be modified thus modifying the wrapper class.
The Liskov Substitution Principle says that you shouldn't make your read-only class inherit from your read-write class, because consuming classes would have to be aware that they can't call the Save method on it without getting an exception.
Making the writable class extend the readable class would make more sense to me, as long as there is nothing on the readable class that indicates its object can never be persisted. For example, I wouldn't call the base class a ReadOnly[Whatever], because if you have a method that takes a ReadOnlyPerson as an argument, that method would be justified in assuming that it would be impossible for anything they do to that object to have any impact on the database, which is not necessarily true if the actual instance is a WriteablePerson.
Update
I was originally assuming that in your read-only class you only wanted to prevent people calling the Save method. Based on what I'm seeing in your answer-response to your question (which should actually be an update on your question, by the way), here's a pattern you might want to follow:
public abstract class ReadablePerson
{
public ReadablePerson(string name)
{
Name = name;
}
public string Name { get; protected set; }
}
public sealed class ReadOnlyPerson : ReadablePerson
{
public ReadOnlyPerson(string name) : base(name)
{
}
}
public sealed class ModifiablePerson : ReadablePerson
{
public ModifiablePerson(string name) : base(name)
{
}
public new string Name {
get {return base.Name;}
set {base.Name = value; }
}
}
This ensures that a truly ReadOnlyPerson cannot simply be cast as a ModifiablePerson and modified. If you're willing to trust that developers won't try to down-cast arguments in this way, though, I prefer the interface-based approach in Steve and Olivier's answers.
Another option would be to make your ReadOnlyPerson just be a wrapper class for a Person object. This would necessitate more boilerplate code, but it comes in handy when you can't change the base class.
One last point, since you enjoyed learning about the Liskov Substitution Principle: By having the Person class be responsible for loading itself out of the database, you are breaking the Single-Responsibility Principle. Ideally, your Person class would have properties to represent the data that comprises a "Person," and there would be a different class (maybe a PersonRepository) that's responsible for producing a Person from the database or saving a Person to the database.
Update 2
Responding to your comments:
While you can technically answer your own question, StackOverflow is largely about getting answers from other people. That's why it won't let you accept your own answer until a certain grace period has passed. You are encouraged to refine your question and respond to comments and answers until someone has come up with an adequate solution to your initial question.
I made the ReadablePerson class abstract because it seemed like you'd only ever want to create a person that is read-only or one that is writeable. Even though both of the child classes could be considered to be a ReadablePerson, what would be the point of creating a new ReadablePerson() when you could just as easily create a new ReadOnlyPerson()? Making the class abstract requires the user to choose one of the two child classes when instantiating them.
A PersonRepository would sort of be like a factory, but the word "repository" indicates that you're actually pulling the person's information from some data source, rather than creating the person out of thin air.
In my mind, the Person class would just be a POCO, with no logic in it: just properties. The repository would be responsible for building the Person object. Rather than saying:
// This is what I think you had in mind originally
var p = new Person(personId);
... and allowing the Person object to go to the database to populate its various properties, you would say:
// This is a better separation of concerns
var p = _personRepository.GetById(personId);
The PersonRepository would then get the appropriate information out of the database and construct the Person with that data.
If you wanted to call a method that has no reason to change the person, you could protect that person from changes by converting it to a Readonly wrapper (following the pattern that the .NET libraries follow with the ReadonlyCollection<T> class). On the other hand, methods that require a writeable object could be given the Person directly:
var person = _personRepository.GetById(personId);
// Prevent GetVoteCount from changing any of the person's information
int currentVoteCount = GetVoteCount(person.AsReadOnly());
// This is allowed to modify the person. If it does, save the changes.
if(UpdatePersonDataFromLdap(person))
{
_personRepository.Save(person);
}
The benefit of using interfaces is that you're not forcing a specific class hierarchy. This will give you better flexibility in the future. For example, let's say that for the moment you write your methods like this:
GetVoteCount(ReadablePerson p);
UpdatePersonDataFromLdap(ReadWritePerson p);
... but then in two years you decide to change to the wrapper implementation. Suddenly ReadOnlyPerson is no longer a ReadablePerson, because it's a wrapper class instead of an extension of a base class. Do you change ReadablePerson to ReadOnlyPerson in all your method signatures?
Or say you decide to simplify things and just consolidate all your classes into a single Person class: now you have to change all your methods to just take Person objects. On the other hand, if you had programmed to interfaces:
GetVoteCount(IReadablePerson p);
UpdatePersonDataFromLdap(IReadWritePerson p);
... then these methods don't care what your object hierarchy looks like, as long as the objects you give them implement the interfaces they ask for. You can change your implementation hierarchy at any time without having to change these methods at all.
Definitely do not make the read-only class inherit from the writable class. Derived classes should extend and modify the capabilities of the base class; they should never take capabilities away.
You may be able to make the writable class inherit from the read-only class, but you need to do it carefully. The key question to ask is, would any consumers of the read-only class rely on the fact that it is read-only? If a consumer is counting on the values never changing, but the writable derived type is passed in and then the values are changed, that consumer could be broken.
I know it is tempting to think that because the structure of the two types (i.e. the data that they contain) is similar or identical, that one should inherit from the other. But that is often not the case. If they are being designed for significantly different use cases, they probably need to be separate classes.
A quick option might be to create an IReadablePerson (etc) interface, which contains only get properties, and does not include Save(). Then you can have your existing class implement that interface, and where you need Read-only access, have the consuming code reference the class through that interface.
In keeping with the pattern, you probably want to have a IReadWritePerson interface, as well, which would contain the setters and Save().
Edit On further thought, IWriteablePerson should probably be IReadWritePerson, since it wouldn't make much sense to have a write-only class.
Example:
public interface IReadablePerson
{
string Name { get; }
}
public interface IReadWritePerson : IReadablePerson
{
new string Name { get; set; }
void Save();
}
public class Person : IReadWritePerson
{
public string Name { get; set; }
public void Save() {}
}
The question is, "how do you want to turn a modifiable class into a read-only class by inheriting from it?"
With inheritance you can extend a class but not restrict it. Doing so by throwing exceptions would violate the Liskov Substitution Principle (LSP).
The other way round, namely deriving a modifiable class from a read-only class would be OK from this point of view; however, how do you want to turn a read-only property into a read-write property? And, moreover, is it desirable to be able to substitute a modifiable object where a read-only object is expected?
However, you can do this with interfaces
interface IReadOnly
{
int MyProperty { get; }
}
interface IModifiable : IReadOnly
{
new int MyProperty { set; }
void Save();
}
This class is assignment compatible to the IReadOnly interface as well. In read-only contexts you can access it through the IReadOnly interface.
class ModifiableClass : IModifiable
{
public int MyProperty { get; set; }
public void Save()
{
...
}
}
UPDATE
I did some further investigations on the subject.
However, there is a caveat to this, I had to add a new keyword in IModifiable and you can only access the getter either directly through the ModifiableClass or through the IReadOnly interface, but not through the IModifiable interface.
I also tried to work with two interfaces IReadOnly and IWriteOnly having only a getter or a setter respectively. You can then declare an interface inheriting from both of them and no new keyword is required in front of the property (as in IModifiable). However when you try to access the property of such an object you get the compiler error Ambiguity between 'IReadOnly.MyProperty' and 'IWriteOnly.MyProperty'.
Obviously, it is not possible to synthesize a property from separate getters and setters, as I expected.
I had the same problem to solve when creating an object for user security permissions, that in certain cases must be mutable to allow high-level users to modify security settings, but normally is read-only to store the currently logged-in user's permissions information without allowing code to modify those permissions on the fly.
The pattern I came up with was to define an interface which the mutable object implements, that has read-only property getters. The mutable implementation of that interface can then be private, allowing code that directly deals with instantiating and hydrating the object to do so, but once the object is returned out of that code (as an instance of the interface) the setters are no longer accessible.
Example:
//this is what "ordinary" code uses for read-only access to user info.
public interface IUser
{
string UserName {get;}
IEnumerable<string> PermissionStrongNames {get;}
...
}
//This class is used for editing user information.
//It does not implement the interface, and so while editable it cannot be
//easily used to "fake" an IUser for authorization
public sealed class EditableUser
{
public string UserName{get;set;}
List<SecurityGroup> Groups {get;set;}
...
}
...
//this class is nested within the class responsible for login authentication,
//which returns instances as IUsers once successfully authenticated
private sealed class AuthUser:IUser
{
private readonly EditableUser user;
public AuthUser(EditableUser mutableUser) { user = mutableUser; }
public string UserName {get{return user.UserName;}}
public IEnumerable<string> PermissionNames
{
//GetPermissions is an extension method that traverses the list of nestable Groups.
get {return user.Groups.GetPermissions().Select(p=>p.StrongName);
}
...
}
A pattern like this allows you to use code you've already created in a read-write fashion, while not allowing Joe Programmer to turn a read-only instance into a mutable one. There are a few more tricks in my actual implementation, mainly dealing with persistence of the editable object (since editing user records is a secured action, an EditableUser cannot be saved with the Repository's "normal" persistence method; it instead requires calling an overload that also takes an IUser which must have sufficient permissions).
One thing you simply must understand; if it is possible for your program to edit the records in any scope, it is possible for that ability to be abused, whether intentionally or otherwise. Regular code reviews of any usage of the mutable or immutable forms of your object will be necessary to make sure other coders aren't doing anything "clever". This pattern also isn't enough to ensure that an application used by the general public is secure; if you can write an IUser implementation, so can an attacker, so you'll need some additional way to verify that your code and not an attacker's produced a particular IUser instance, and that the instance hasn't been tampered with in the interim.
I'm currently struggling to understand how I should organize/structure a class which I have already created. The class does the following:
As its input in the constructor, it takes a collection of logs
In the constructor it validates and filters the logs through a series of algorithms implementing my business logic
After all filtering and validation is complete, it returns a collection (a List) of the valid and filtered logs which can be presented to the user graphically in a UI.
Here is some simplified code describing what I'm doing:
class FilteredCollection
{
public FilteredCollection( SpecialArray<MyLog> myLog)
{
// validate inputs
// filter and validate logs in collection
// in end, FilteredLogs is ready for access
}
Public List<MyLog> FilteredLogs{ get; private set;}
}
However, in order to access this collection, I have to do the following:
var filteredCollection = new FilteredCollection( specialArrayInput );
//Example of accessing data
filteredCollection.FilteredLogs[5].MyLogData;
Other key pieces of input:
I foresee only one of these filtered collections existing in the application (therefore should I make it a static class? Or perhaps a singleton?)
Testability and flexibility in creation of the object is important (Perhaps therefore I should keep this an instanced class for testability?)
I'd prefer to simplify the dereferencing of the logs if at all possible, as the actual variable names are quite long and it takes some 60-80 characters to just get to the actual data.
My attempt in keeping this class simple is that the only purpose of the class is to create this collection of validated data.
I know that there may be no "perfect" solution here, but I'm really trying to improve my skills with this design and I would greatly appreciate advice to do that. Thanks in advance.
EDIT:
Thanks to all the answerers, both Dynami Le-Savard and Heinzi identified the approach I ended up using - Extension Methods. I ended up creating a MyLogsFilter static class
namespace MyNamespace.BusinessLogic.Filtering
{
public static class MyLogsFilter
{
public static IList<MyLog> Filter(this SpecialArray<MyLog> array)
{
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
}
}
and I can create a read only collection of this in code by doing
IList<MyLog> filteredLogs = specialArrayInput.Filter();
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
It sounds like you do three things to your logs:
Validate them
Filter them
and
Access them
You want to store the logs in a collection. The standard List collection is a good fit since it doesn't care what's in it, gives you LINQ and allows you to lock the collection with a read-only wrapper
I would suggest you separate your concerns into the three steps above.
Consider
interface ILog
{
MarkAsValid(bool isValid);
... whatever data you need to access...
}
Put your validation logic in a separate interface class
interface ILogValidator
{
Validate(ILog);
}
And your filtering logic in yet another
interface ILogFilter
{
Accept(ILog);
}
Then with LINQ, something like:
List<MyLog> myLogs = GetInitialListOfLogsFromSomeExternalSystem();
myLogs.ForEach(x => MyLogValidator(x));
List<MyLog> myFilteredLogs = myLogs.Where(x => MyLogFilter(x));
The separation of concerns makes testing and maintainability much better. And stay away from the singletons. For many reasons including testability they are out of favor.
The way I see it, you are looking at a method that returns a collection of filtered log, rather than a collection class wrapping your business logic. Like so:
class SpecialArray<T>
{
[...]
public IEnumerable<T> Filter()
{
// validate inputs
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
[...]
}
However, it does look like what you really wish is actually to separate the business logic in charge of filtering the logs from the SpecialArray class, perhaps because you feel like the logic touches many things that do not really concern SpecialArray, or because Filter does not apply to all generic cases of SpecialArray.
In that case my suggestion would be to isolate your business logic in another namespace, perhaps one that uses and/or requires other components in order to apply said business logic, and offer your functionality as an extension method, concretly :
namespace MyNamespace.Collections
{
public class SpecialArray<T>
{
// Shenanigans
}
}
namespace MyNamespace.BusinessLogic.Filtering
{
public static class SpecialArrayExtensions
{
public static IEnumerable<T> Filter<T>(this SpecialArray<T> array)
{
// validate inputs
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
}
}
And when you need to use that business logic, it would look like this :
using MyNamespace.Collections; // to use SpecialArray
using MyNamespace.BusinessLogic.Filtering; // to use custom log filtering business logic
namespace MyNamespace
{
public static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main2()
{
SpecialArray<Logs> logs;
var filteredLogs = logs.Filter();
}
}
}
Some thoughts:
As you correctly point out, using an instanced class improves testability.
Singletons should be used if (A) there is only one instance of the class in your whole system and (B) you need to access this instance at multiple different places of your application without having to pass the object around. Unnecessary use of the Singleton pattern (or any other kind of "global state") should be avoided, so unless (B) is satisfied in your case as well, I'd not use a singleton here.
For simple dereferencing, consider using an indexer. This will allow you to write:
FilteredCollection filteredlogs = new FilteredCollection( secialArrayInput );
//Example of accessing data
filteredlogs[5].MyLogData;
If your class only consists of a constructor and a field to access the result, using a simple method might be more appropriate than using a class. If you want to do it the fancy way, you could write it as an extension method for SpecialArray<MyLog>, allowing you to access it like this:
List<MyLog> filteredlogs = secialArrayInput.Filter();
//Example of accessing data
filteredlogs[5].MyLogData;
If you want to inherit the interface of SpecialArray for you final filtered array then derive from SpecialArray instad of having an instance member. That would allow:
filteredCollecction[5].MyLogData;
etc..
I am not sure if there is already a nomenclature for this, but for the sake of this question lets define two terms: peer implementation or nested implementation to illustrate how you implement collection classes in a data model that contains many parent/child entity relationships.
I use the term peer to describe the scenario where you implement the collection classes in your model layer along side with the entity classes essentially making them peers in your API like so:
public class ParentEntity
{
private ChildEntityCollection children;
}
public class ChildEntity
{
}
public class ChildEntityCollection : ICollection<ChildEntity>
{
}
The main advantage here is that you can reuse the collection class in other entity classes that happen to store children of the same type.
I use the term nested to describe the scenario where you implement them as a nested class like so:
public class ParentEntity
{
private ChildEntityCollection children;
public class ChildEntityCollection : ICollection<ChildEntity>
{
}
}
public class ChildEntity
{
}
The main advantage here is that each parent can implement their own collection class to store its children in manner that is most optimized for that specific parent. For example, one parent entity may find that an array data structure works well whereas another may use a splay tree (obscure I know, but it illustrates my point well).
I have noticed that Microsoft uses both idioms in the various .NET related frameworks. The System.Windows.Forms namespace seems to rely heavily on nested implementations. I tend to find myself prefering this method as well even though it requires more work.
Recommendations, comments, alternative ideas?
Regardless of what Microsoft might have done in the past, the current .NET API design guidelines discourage creation of nested classes that are visible outside their parent classes. See http://msdn.microsoft.com/en-us/library/ms229027.aspx for details.
Another option is to nest the collection class in the child class, and just name it Collection. That way, you always get Child.Collection as the name.
public class Child
{
public class Collection : ICollection<Child>
{
}
}
public class Parent
{
private Child.Collection children;
}
Personally I prefer the peer implementation, it promotes reuse of code which I don't think the nested implementation does. If another class needs to implement a different way of storing a collection of the same elements then another class can easily be implemented for that scenario without limiting code reuse.
A nested setup can also lead some developers to tightly couple their code to the parent class.
I also prefer the peer approach. There's really no reason to nest the collection unless you will never use it outside of its parent class (in that case, it should be a private nested class.)
I would only use the nested arrangement when there is only one Entity in the Domain model that can logically contain the child Entities.
For example if you had a PieceOfMail class and a MailPieces collection class
class PieceOfMail { }
class MailPieces: Collection<PieceOfMail> { }
then the ShipingCompany class, and the MailBox class, and the PostOffice Class, and the MailRoute class, and the MailManBag class, could ALL have a constituent property typed as MailPieces, so I'd use the "peer" technique.
But otoh, in the same Domain, if you had a class representing a type of PostageDiscount, and a collection class representing a set of discounts to be applied to a shipment, it might be the case that ONLY the ShipmentTransaction class could logically contain a collection of those discounts, then I'd use the nested technique...
Do you really need a ChildEntityCollection? Why not use a collection type that is provided?
//why bother?
//public class ChildEntityCollection : ICollection<ChildEntity>{}
public class ParentEntity
{
//choose one
private ChildEntity[] children;
private List<ChildEntity> childrenInList;
private HashSet<ChildEntity> childrenInHashSet;
private Dictionary<int, ChildEntity> childrenInDictionary;
// or if you want to make your own, make it generic
private Balloon<ChildEntity> childrenInBalloon;
}
public class ChildEntity
{
}
I generally try to avoid generating specific collection classes. Sometimes you may need a special class, but in many cases you can simply use generic classes like Collection<T> and ReadOnlyCollection<T> from the System.Collection.ObjectModel namespace. This saves a lot of typing. All your collections derive from IEnumerable<T> etc. and are easily integrated with LINQ. Depending on your requirements you could also expose your collections as ICollection<T> or another collection interface and then let classes with specific requirements use highly optimized generic collections.
public class ParentEntity {
Collection<ChildEntity> children = new Collection<ChildEntity>();
public Collection<ChildEntity> Children {
get {
return this.children;
}
}
}
You can also wrap an IList<T> like this:
public class ParentEntity {
// This collection can be modified inside the class.
List<ChildEntity> children = new List<ChildEntity>();
ReadOnlyCollection<ChildEntity> readonlyChildren;
public ReadOnlyCollection<ChildEntity> Children {
get {
return this.readOnlyChildren
?? (this.readOnlyChildren =
new ReadOnlyCollection<ChildEntity>(this.children));
}
}
}