I am writing a class library for financial modeling.
I want to define the models using interfaces to create abstraction for testing, and the possible later addition of new concrete classes.
I am struggling on how to define lists of things, so I can later add to those lists in the concrete class.
For example, if I define an interface as having a list of expenses in my Model called
IEnumerable Expenses {get; set;}
and later want to create a concrete class called ABCModel with a list of concrete XYZExpense in it, what would be the best way to implement the lists so I can easily add more items to the list?
I cannot cast the List as a IEnumerable.
So for example:
public interface IFinancialModel
{
IEnumerable<IExpense> Expenses { get; }
IEnumerable<IRevenue> Revenue { get; }
IEnumerable<IAsset> Assets { get; }
IEnumerable<ILiability> Liabilities { get; }
}
I need a concrete class called public class FinancialModel : IFinancialModel
and be able to add concrete items.
Should I create 'Add' methods of my own? Ideally I would like to leverage built in List functionality and not reinvent the wheel.
It depends on what you actually want to do. Having List or IList properties is not recommended, because you can do everything with it (like Clear, Add and so on) without the owning class know about it. This is not good for encapsulation. You wouldn't be able to do something on change (like setting a dirty flag, fire changed events or do validation).
IEnumerable is a good choice.
You may add setters, but you shouldn't take the value that is set to the property by reference. It could be anything, like a Linq query or even a database query, which you don't want to reference to. You only want the items. (Also consider that the reference to the collection which comes from the outside can be assigned to other instances, which results in very bad side effects when it is changed there but shouldn't be changed here.)
// example implementation with a setter
private List<IExpense> expenses
public IEnumerable<IExpense> Expenses
{
get { return expenses; }
set { expenses = value.ToList(); }
}
Alternatively you may implement your own Add, AddRange, Remove or Clear etc. methods. However, if the main use case is to set all items in one go, you can only have a SetExpenses method, which is the same as the setter on the property I showed before. You may consider to keep it as an array internally.
What you are looking for is IList<T>. This is an interface that allows you to expose the lists while hiding the actual list implementation. For ex:
interface IFinancialModel {
IList<IExpense> Expenses { get; }
}
Then implement with a list that satisfies your needs. For example:
class FinancialModel : IFinancialModel {
private IList<IExpense> _expenses = new List<IExpense>();
IList<IExpense> Expenses { get { return _expenses; } }
}
I agree with #Stefan though, exposing a list breaks encapsulation and should generally be avoided.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
why use IList or List?
I have the following:
public class CityViewModel
{
public CityViewModel() {
Details = Enumerable.Range(1,10).Select(x => new City.Detail()).ToList();
}
public string Topic { get; set; }
public City City { get; set; }
public IList<City.Detail> Details { get; set; }
}
The suggestion as a way to create Details was given to me. What I am unsure about is why the following line is declared as an IList:
public IList<City.Detail> Details { get; set; }
Would it not be more correct to declare this as:
public List<City.Detail> Details { get; set; }
Can someone explain the difference to me.
IList<T> is an interface. List<T> is a concrete type.
If you want to be telling the user less about your internal implementations (and usually that is something you want to avoid), then you should use IList<T> - as you're then free to switch to anything that implements that interface... Which may be an adapter or wrapper of some kind - or a mock for testing.
I'd also consider whether you really need to return a list style object or whether using IEnumerable<T> may better suit your needs (if you're just iterating through that list). You'd only need the list if you needed length and direct indexing I think - and even then creating a list from an IEnumerable<T> is easy.
public IEnumerable<City.Detail> Details { get; private set; }
This is probably what you want to START from as an interface for your class. Expose the minimum necessary capabilities and don't allow external classes to modify the members OR the collection.
Only expose additional functionality (IList) if you need it and only expose a setter if you absolutely need it.
Using an interface rather than the class is definitely the right way to go, both for information hiding and testability reasons. I would even go further, and suggest using ICollection<T> instead of IList<T> if you can: this would give you even more flexibility as far as choosing an alternative implementation goes, while letting your users perform mostly the same operations.
Moreover, I would probably not use an automatic assignable property for it: I'd return a read-only version, and provided separate methods for manipulating the list on my own class.
Here is what I would do:
public class CityViewModel {
private readonly List<City.Detail> details;
public CityViewModel() {
// Here you assign a List to details
}
public ICollection<City.Detail> Details {
get {
return details.AsReadOnly();
}
}
}
This hides implementation of the list from users, does not let them modify the list behind your back, and does not even tell them that you're using a List. If you would decide to use, say, a HashSet at some later date, you'd be able to swap it in without a fear of breaking something in the code that uses your class.
My view on this is that returning IList enables the callers of your method to be agnostic of the underlying implementation. Meaning if you change your implementation inside your method to another collection that also implements IList, you don't have to update any of the callers. Whereas if you return a concrete List, all callers have to be updated if you make a change to the underlying collection type.
Basic difference between IList and List is that IList is an Interface where List is Class. So if you use List you get more built in function to do search or data maniputation.
List
IList
In many of our projects I have seen a few custom collection / or container classes that hold a some sort of generic collection, e.g. a List(of T) class.
They usually have a GetXXX method that returns a IEnumerable of whatever type the custom collection class uses so the internal collection can be iterated around using a foreach loop.
e.g.
public IEnumerable<UploadState> GetStates
{
get
{
return new List<UploadState>(m_states);
}
}
My question is that should these classes instead implement the IEnumerable interface, and call GetEnumerator on the List itself.
Is there a preferred way, or is it up to the developer?
If your class is a custom collection class then yes, it should implement IEnumerable<T>. In this case a public property for the inner list would be redundant. Imagine a simple class:
public class People : IEnumerable<Person>
{
List<Person> persons = new List<Person>();
public IEnumerator<Person> GetEnumerator()
{
return persons.GetEnumerator();
}
}
But if your class cannot act like a collection then provide a public IEnumerable property for its elements:
public class Flight
{
List<Person> passengers = new List<Person>();
public IEnumerable<Person> Passengers
{
get { return passengers; }
}
}
Anyway, it's always up to the developer to choose the right design.
I would do it that way:
public IEnumerable<UploadState> GetStates
{
get
{
foreach (var state in m_states) {
yield return state;
}
}
}
It is cleaner, your users don't get a list where they shouldn't (they could cast it to a List<T>after all) and you don't need to create a List<T>object.
EDIT: Misunderstood the question. I think if the class is meant to be a collection, it should implement IEnumerable<T>.
Consider that in your code example a new list created. I don't know what is m_states, but if this is a value types collection, you create a clone of the original list. In this way the returning list can be manipulated form the caller Add/Remove/Update elements. without affectiing original data.
If m_states are reference types, this still creates a new list which can be again manipulated by the caller Add/Remove/ No update elements (it's a reference!) without affecting original data.
What about IEnumerable<T>, its just a way to make a returning type generic, and not make strong coupling to List<T> type.
I think if your newly implemented class just behaves the sameway as a list does, there is no need to implement it. If you need some kind of custom logic, it depends on what you want to do; you can inherit list or you can implement IEnumerable. It just depends what is to be achieved.
You might want to check this:
http://www.codeproject.com/Articles/4074/Using-IEnumerator-and-IEnumerable-in-the-NET-Frame
I didn't read fully it yet, but I think this answers your question.
You should be deriving your custom collection classes based on one of the classes in System.Collections.ObjectModel namespace. They already contain implementations of IEnumerable<T> and the non generic IEnumerable interfaces.
I have a class called GestorePersonale which holds a list of instances of another class:
public List<Dipendente> Dipendenti
{
get;
private set;
}
I want to keep this list modifiable only from the methods the class exposes, and not directly. I noticed that with the code above, one could just do var gp = new GestorePersonale();
gp.Dipendenti.Add( new Dipendente( ... ) );
and be able to perform any other kind of action on the List<Dipendente> itself.
I considered converting the first code snippet to
private List dipendenti;
but I could find a few downsides to that:
This would break the personal rule of mine to try to always use the public fields over the private ones from inside the class's methods whenever possible (even though I'm not sure if it is good practice to do so, so any clarification would be welcome);This would impair any external entities' ability to access the contents of the list for reading purposes only, like, say, to execute a LINQ query over the contents of the list.
What would be the best way to solve this situation?
You can wrap the list in a ReadOnlyCollection<T> and expose that:
private List<Dipendente> dipendenti;
private ReadOnlyCollection<Dipendente> readOnlyDipendenti;
public GestorePersonale()
{
dipendenti = new List<Dipendente>();
readOnlyDipendenti = new ReadOnlyCollection<Dipendente>(dipendenti);
}
public ReadOnlyCollection<Dipendente> Dipendenti
{
get { return readOnlyDipendenti; }
}
Internally, you have access to dipendenti and can add/remove items. External entities have access only to the ReadOnlyCollection<T> that wraps the list, so they can only read, but not add/remove items.
I would agree with dtb that ReadOnlyCollections is the way to go. However, you can return it from the property getter (using AsReadOnly) and drop the method.
private List<Dipendente> dipendenti = new List<Dipendente>();
public ReadOnlyCollection<Dipendente> ReadOnlyDipendenti
{
get
{
return dipendenti.AsReadOnly();
}
}
there are a couple of things you can do:
you use ReadOnlyCollection
you can return an IEnumerable<_type>
you can wrap the list in another class
you can roll your own collection class, implementing the appropriate interface
the method you use depends on the functionality you need and what you want/need to expose to the user of your class
What you have is a public property with a private accessor. It is very useful. It allows an instance to expose a value that is controlled (set) by the instance itself, e.g. a state.
For example, take a collection with a Count property. It makes no sense for it have a public accessor. An implementation could be to update the property (internally) when the collection is changed (to avoid having to count it each time).
Do a setter method or wrap the field in another class. This is a classic collection set and collection.add problem.
I know there has been a lot of posts on this but it still confuses me why should you pass in an interface like IList and return an interface like IList back instead of the concrete list.
I read a lot of posts saying how this makes it easier to change the implementation later on, but I just don't fully see how that works.
Say if I have this method
public class SomeClass
{
public bool IsChecked { get; set; }
}
public void LogAllChecked(IList<SomeClass> someClasses)
{
foreach (var s in someClasses)
{
if (s.IsChecked)
{
// log
}
}
}
I am not sure how using IList will help me out in the future.
How about if I am already in the method? Should I still be using IList?
public void LogAllChecked(IList<SomeClass> someClasses)
{
//why not List<string> myStrings = new List<string>()
IList<string> myStrings = new List<string>();
foreach (var s in someClasses)
{
if (s.IsChecked)
{
myStrings.Add(s.IsChecked.ToString());
}
}
}
What do I get for using IList now?
public IList<int> onlySomeInts(IList<int> myInts)
{
IList<int> store = new List<int>();
foreach (var i in myInts)
{
if (i % 2 == 0)
{
store.Add(i);
}
}
return store;
}
How about now? Is there some new implementation of a list of int's that I will need to change out?
Basically, I need to see some actual code examples of how using IList would have solved some problem over just taking List into everything.
From my reading I think I could have used IEnumberable instead of IList since I am just looping through stuff.
Edit
So I have been playing around with some of my methods on how to do this. I am still not sure about the return type(if I should make it more concrete or an interface).
public class CardFrmVm
{
public IList<TravelFeaturesVm> TravelFeaturesVm { get; set; }
public IList<WarrantyFeaturesVm> WarrantyFeaturesVm { get; set; }
public CardFrmVm()
{
WarrantyFeaturesVm = new List<WarrantyFeaturesVm>();
TravelFeaturesVm = new List<TravelFeaturesVm>();
}
}
public class WarrantyFeaturesVm : AvailableFeatureVm
{
}
public class TravelFeaturesVm : AvailableFeatureVm
{
}
public class AvailableFeatureVm
{
public Guid FeatureId { get; set; }
public bool HasFeature { get; set; }
public string Name { get; set; }
}
private IList<AvailableFeature> FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm)
{
List<AvailableFeature> availableFeatures = new List<AvailableFeature>();
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
availableFeatures.Add(availableFeature);
}
}
return availableFeatures;
}
Now I am returning IList for the simple fact that I will then add this to my domain model what has a property like this:
public virtual IList<AvailableFeature> AvailableFeatures { get; set; }
The above is an IList itself as this is what seems to be the standard to use with nhibernate. Otherwise I might have returned IEnumberable back but not sure. Still, I can't figure out what the user would 100% need(that's where returning a concrete has an advantage over).
Edit 2
I was also thinking what happens if I want to do pass by reference in my method?
private void FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm, IList<AvailableFeature> toFill)
{
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
toFill.Add(availableFeature);
}
}
}
would I run into problems with this? Since could they not pass in an array(that has a fixed size)? Would it be better maybe for a concrete List?
There are three questions here: what type should I use for a formal parameter? What should I use for a local variable? and what should I use for a return type?
Formal parameters:
The principle here is do not ask for more than you need. IEnumerable<T> communicates "I need to get the elements of this sequence from beginning to end". IList<T> communicates "I need to get and set the elements of this sequence in arbitrary order". List<T> communicates "I need to get and set the elements of this sequence in arbitrary order and I only accept lists; I do not accept arrays."
By asking for more than you need, you (1) make the caller do unnecessary work to satisfy your unnecessary demands, and (2) communicate falsehoods to the reader. Ask only for what you're going to use. That way if the caller has a sequence, they don't need to call ToList on it to satisfy your demand.
Local variables:
Use whatever you want. It's your method. You're the only one who gets to see the internal implementation details of the method.
Return type:
Same principle as before, reversed. Offer the bare minimum that your caller requires. If the caller only requires the ability to enumerate the sequence, only give them an IEnumerable<T>.
The most practical reason I've ever seen was given by Jeffrey Richter in CLR via C#.
The pattern is to take the basest class or interface possible for your arguments and return the most specific class or interface possible for your return types. This gives your callers the most flexibility in passing in types to your methods and the most opportunities to cast/reuse the return values.
For example, the following method
public void PrintTypes(IEnumerable items)
{
foreach(var item in items)
Console.WriteLine(item.GetType().FullName);
}
allows the method to be called passing in any type that can be cast to an enumerable. If you were more specific
public void PrintTypes(List items)
then, say, if you had an array and wished to print their type names to the console, you would first have to create a new List and fill it with your types. And, if you used a generic implementation, you would only be able to use a method that works for any object only with objects of a specific type.
When talking about return types, the more specific you are, the more flexible callers can be with it.
public List<string> GetNames()
you can use this return type to iterate the names
foreach(var name in GetNames())
or you can index directly into the collection
Console.WriteLine(GetNames()[0])
Whereas, if you were getting back a less specific type
public IEnumerable GetNames()
you would have to massage the return type to get the first value
Console.WriteLine(GetNames().OfType<string>().First());
IEnumerable<T> allows you to iterate through a collection. ICollection<T> builds on this and also allows for adding and removing items. IList<T> also allows for accessing and modifying them at a specific index. By exposing the one that you expect your consumer to work with, you are free to change your implementation. List<T> happens to implement all three of those interfaces.
If you expose your property as a List<T> or even an IList<T> when all you want your consumer to have is the ability to iterate through the collection. Then they could come to depend on the fact that they can modify the list. Then later if you decide to convert the actual data store from a List<T> to a Dictionary<T,U> and expose the dictionary keys as the actual value for the property (I have had to do exactly this before). Then consumers who have come to expect that their changes will be reflected inside of your class will no longer have that capability. That's a big problem! If you expose the List<T> as an IEnumerable<T> you can comfortably predict that your collection is not being modified externally. That is one of the powers of exposing List<T> as any of the above interfaces.
This level of abstraction goes the other direction when it belongs to method parameters. When you pass your list to a method that accepts IEnumerable<T> you can be sure that your list is not going to be modified. When you are the person implementing the method and you say you accept an IEnumerable<T> because all you need to do is iterate through that list. Then the person calling the method is free to call it with any data type that is enumerable. This allows your code to be used in unexpected, but perfectly valid ways.
From this it follows that your method implementation can represent its local variables however you wish. The implementation details are not exposed. Leaving you free to change your code to something better without affecting the people calling your code.
You cannot predict the future. Assuming that a property's type will always be beneficial as a List<T> is immediately limiting your ability to adapt to unforeseen expectations of your code. Yes, you may never change that data type from a List<T> but you can be sure that if you have to. Your code is ready for it.
Short Answer:
You pass the interface so that no matter what concrete implementation of that interface you use, your code will support it.
If you use a concrete implementation of list, another implementation of the same list will not be supported by your code.
Read a bit on inheritance and polymorphism.
Here's an example: I had a project once where our lists got very large, and resulting fragmentation of the large object heap was hurting performance. We replaced List with LinkedList. LinkedList does not contain an array, so all of a sudden, we had almost no use of the large object heap.
Mostly, we used the lists as IEnumerable<T>, anyway, so there was no further change needed. (And yes, I would recommend declaring references as IEnumerable if all you're doing is enumerating them.) In a couple of places, we needed the list indexer, so we wrote an inefficient IList<T> wrapper around the linked lists. We needed the list indexer infrequently, so the inefficiency was not a problem. If it had been, we could have provided some other implementation of IList, perhaps as a collection of small-enough arrays, that would have been more efficiently indexable while also avoiding large objects.
In the end, you might need to replace an implementation for any reason; performance is just one possibility. Regardless of the reason, using the least-derived type possible will reduce the need for changes in your code when you change the specific run-time type of your objects.
Inside the method, you should use var, instead of IList or List. When your data source changes to come from a method instead, your onlySomeInts method will survive.
The reason to use IList instead of List as parameters, is because many things implement IList (List and [], as two examples), but only one thing implements List. It's more flexible to code to the interface.
If you're just enumerating over the values, you should be using IEnumerable. Every type of datatype that can hold more than one value implements IEnumerable (or should) and makes your method hugely flexible.
Using IList instead of List makes writing unit tests significantly easier. It allows you to use a 'Mocking' library to pass and return data.
The other general reason for using interfaces is to expose the minimum amount of knowledge necessary to the user of an object.
Consider the (contrived) case where I have a data object that implements IList.
public class MyDataObject : IList<int>
{
public void Method1()
{
...
}
// etc
}
Your functions above only care about being able to iterate over a list. Ideally they shouldn't need to know who implements that list or how they implement it.
In your example, IEnumerable is a better choice as you thought.
It is always a good idea to reduce the dependencies between your code as much as possible.
Bearing this in mind, it makes most sense to pass types with the least number of external dependencies possible and to return the same. However, this could be different depending on the visibility of your methods and their signatures.
If your methods form part of an interface, the methods will need to be defined using types available to that interface. Concrete types will probably not be available to interfaces, so they would have to return non-concrete types. You would want to do this if you were creating a framework, for example.
However, if you are not writing a framework, it may be advantageous to pass parameter with the weakest possible types (i.e. base classes, interfaces, or even delegates) and return concrete types. That gives the caller the ability to do as much as possible with the returned object, even if it is cast as an interface. However, this makes the method more fragile, as any change to the returned object type may break the calling code. In practice though, that generally isn't a major problem.
You accept an Interface as a parameter for a method because that allows the caller to submit different concrete types as arguments. Given your example method LogAllChecked, the parameter someClasses could be of various types, and for the person writing the method, all might be equivalent (i.e. you'd write the exact same code regardless of the type of the parameter). But for the person calling the method, it can make a huge difference -- if they have an array and you're asking for a list, they have to change the array to a list or v.v. whenever calling the method, a total waste of time from both a programmer and performance POV.
Whether you return an Interface or a concrete type depends upon what you want to let your callers do with the object you created -- this is an API design decision, and there's no hard and fast rule. You have to weigh their ability to make full use of the object against their ability to easily use a portion of the objects functionality (and of course whether you WANT them to be making full use of the object). For instance, if you return an IEnumerable, then you are limiting them to iterating -- they can't add or remove items from your object, they can only act against the objects. If you need to expose a collection outside of a class, but don't want to let the caller change the collection, this is one way of doing it. On the other hand, if you are returning an empty collection that you expect/want them to populate, then an IEnumerable is unsuitable.
Here's my answer in this .NET 4.5+ world.
Use IList<T> and IReadonlyList<T>,
instead of List<T>, because ReadonlyList<T> doesn't exist.
IList<T> looks so consistent with IReadonlyList<T>
Use IEnumerable<T> for minimum exposure (property) or requirement (parameter) if foreach is the only way to use it.
Use IReadonlyList<T> if you also need to expose/use Count and [] indexer.
Use IList<T> if you also allow callers to add/update/delete elements
because List<T> implements IReadonlyList<T>, it doesn't need any explicit casting.
An example class:
// manipulate the list within the class
private List<int> _numbers;
// callers can add/update/remove elements, but cannot reassign a new list to this property
public IList<int> Numbers { get { return _numbers; } }
// callers can use: .Count and .ReadonlyNumbers[idx], but cannot add/update/remove elements
public IReadOnlyList<int> ReadonlyNumbers { get { return _numbers; } }
In a C# (visual Studio 2010) project, I have a class with large number of properties, and I populate objects of this class with data and add to list object to pass it to display list of items (Something like results of a search).
My problem is there I don't need all the properties of the class to display the above list, so do I have to create another class only with required field to display the (results) list? Is it correct according to the OOP concepts?
Your properties object can implement multiple interfaces, as requested by different parts of your program.
If you define these interfaces:
public interface IBasicInfo
{
string Name { get; }
string Id { get; }
}
internal interface IFullInfo : IBasicInfo
{
string Address { get; }
}
internal interface IInternalStuff
{
Stuff Data { get; }
}
And your properties class implements them like this:
internal class Properties : IFullInfo, IInternalStuff
{
// some basic implementation
}
Then you can pass this class to a different part of your app which has a method like this:
public void Display(IBasicInfo info)
{
...
}
And the calling code will only see properties which belong to IBasicInfo. Note that only IBasicInfo needs to be public, and even the Properties class is internal to ensure that no calling code can cast back to the actual implementation and mess with it.
Alternatively, if your calling code contains completely different interfaces, then it is perfectly reasonable to convert them into Data Transfer Objects, and even modify their contents to match caller's expectations (adapter pattern). There are tools which automate this task (Automapper, for example).
I think yes, it is called Data transfer object
You might consider using a solution like automapper to map from a class that has N number of properties to another that has M number of properties. It relies on some conventional information (same/similar name) but can be tweaked too.
This is a pretty standard way of taking model data pulled from a DB and converting it into something that can be displayed on a view in webpage. I build a "viewmodel" that just has the stuff I want to display, which is typically a subset of the fields, and then map between them. Something like automapper makes it pretty easy to do so.
Since you have a reference type (a class), it shouldn't be costly to pass the original object rather than a new object containing a subset of the data.
If you want to protect the object from being manipulated by the recipient of the list, then you could define a read-only interface for the class, and pass it as that.