How to override List<T>.IsReadOnly in C# - c#

I'm trying to derive from List and selectively turn the IsReadOnly property on and off. I was hoping that the Add/Remove/[] functions would honor this property, but they don't.
What's the right way of doing this?
My derived class has some additional properties, so I can't unfortunately just wrap the list in ReadOnlyCollection.

Use encapsulation instead of inheritance in this case.
You should just make your class implement IList<T>, and have a private List<T> variable.
You can pass through any functions you wish, but also can completely override them, change behavior, etc. This gives you complete control (at the expense of having many methods that does nothing but call this.List.method(...) ).
In general, I don't think it's a good idea to inherit from the BCL collection classes in any case. I prefer to make them an implementation detail internal in my class.

List<T> is by definition a mutable type. There's no way to make it read-only.
If you're making a derived class, you should probably be implementing IList<T> directly rather than subclassing List<T> anyway. This will give you full control over the implementation, allowing you to make it read-only if you wish.

You could call the "AsReadOnly" method on list which should return to you an IList instance that should honor that it is...err...read-only.
...OK, I just read your last sentence, my bad. In which case maybe you just want to implement the IList interface or any friend and just route most of the interface to a list you keep internally. Then you can build this behaviour. Even so, I would do a similar pattern, provide some "AsReadOnly" method that explicitly gives you something that is read-only.

Related

Avoid Generic Lists in Base Class - Should I Follow the Same Rule for Dictionary?

I was advised to change a List<string> property to a Collection<string>, in a base class, because it is more appropriate for inheritance.
This 'rule' was referred to: https://msdn.microsoft.com/en-us/library/ms182142.aspx
System.Collections.Generic.List is a generic collection that is
designed for performance and not inheritance.
System.Collections.Generic.List does not contain virtual members
that make it easier to change the behavior of an inherited class. The
following generic collections are designed for inheritance and should
be exposed instead of System.Collections.Generic.List.
System.Collections.ObjectModel.Collection<T>
System.Collections.ObjectModel.ReadOnlyCollection<T>
System.Collections.ObjectModel.KeyedCollection<TKey, TItem>
Does a similar rule apply to Dictionary<string, string>?
I ask because it is also in the System.Collections.Generic namespace. Or maybe I have misunderstood and the rule only applies to Lists.
BTW, the Dictionary purpose is to hold errors (in a similar format to ModelState). I am not currently sure at exactly what stage I will be adding errors to it.
If I should be avoiding Dictionary<string, string> in the base class, what should I be using in it's place?
I have come across KeyedCollection but not sure if that is a good replacement.
Dictionary<TKey, TValue> does not have any base class you can use instead of it. It may be better to use interface (IDictionary<TKey, TValue> or maybe IReadOnlyDictionary<TKey, TValue> -both implemented by Dictionary), but it depends on your needs.
Note that it is very hard to express whether property returns internal storage or clone (and hence what happens when caller changes object) - you may want to consider IEnumerable<T> or methods that hide dictionary as implementation details.
So basically what you were told could potentially be wrong for the use case you are going for.
The statement in the msdn article means by inheritance if you want to create your own implementation of a collection by deriving from it like so:
public class MyCollection : Collection<MyType>
The advantage of using Collection<T> in this scenario is that you can alter the behavior significantly as it exposes the following methods which can be overriden: ClearItems, InsertItem, RemoveItem and SetItem. When you derive from List<T> you can't override any methods at all (except for the standard ToString, Equals and GetHashCode).
But as you stated in your comment you use the List/Dictionary/Collection as a property. Therefore it rather depends on your own use case.
If you want deriving classes to just use the collection from the base class you can let it be whatever you think is best suited for your needs. But if you think that the deriving class will know better which collection to use then you should
pick an interface from the System.Collections.Generic namespace.
I won't tell you which types or interfaces you should use when as it heavily depends on which functionality you need.
And by the way: the KeyedCollection can only be used to create your own key value collection (it is abstract). Therefore having a KeyedCollection as a property would mean that you'd also need an implementaion of a KeyedCollection.

Inheriting from List<myType> or Extending List<myType>

If I'm creating a class, MyWrapper, to wrap a List of objects from myClass, should MyWrapper inherit from List<T>? Or List<myClass>?
Or should I just create some extension methods for List<myClass>?
I know it's against the guideliness to inherit from List<T>, but why?
Is there any drawback for inheriting from List<Point> or List<T>?
Is there any drawback for creating extension methods for List<T>? And what about creating extension methods for List<myType>?
And a example for a extension method valid for List would be
public static void Swap<T>(this List<T> list, int firstIndex, int secondIndex)
{...}
You can't just add extension methods to List, because you won't be able to code to the shape of all types of T. What if it's a List<People>? What would "MoveTo" or "GetCenter" do in that case?
Yes, you should make a new class that inherits from List, or better yet, IList.
Or you could just model your "Point" class, then have a List<Point>, and if you wanted to add extension methods to List<Point> you could do that.
If you choose to derive List<>, the most evident drawback is that your user can't "guess" which method is overriden, and which ones is provided "as is". List is very rich class, especially when extended with LINQ, and a custom overriding of it can quickly be misleading and bug prone.
If you would like to provide List "as is", with a few custom methods, Extension Methods for List (where you target your specific kind of "T" !) could be really helpful and allow to preserve the original behavior of List.
Users will enable and use your Extension Methods only if they need them.
The drawbacks are the evident ones of Extension Methods : you can't do everything you want in them. There are plenty informations on web on Extension Methods.
IHMO the best thing to do is to encapsulate the List (or other enumerable) in your own class. Of course, T is specific to your own case.
The drawback is the need to redefine all relevant methods. Of course you can also expose the inner list (or, better, a Read only copy of it) with a specific property to allow user to directly use it. Your class can also implement IEnumerable.
Please also note that there are already tons of useful rewriting and extending methods and full custom collection implementation to improve List and other collections types on the web, and in Framework itself (most of collection types are misused, and LINQ adds a lot of good things). Take care to not reinvent the wheel.

When some methods will not be used/not implemented, use an Interface or Abstract Class?

I have a project where quite a few functions and variable getters will be defined, abstractly. My question is should I use an abstract class for this(with each function throwing NotImplementedException), or should I just use an interface? Or should I use both, making both an interface and then an abstract class implementing the interface?
Note, even though all of these functions and such may be defined, it does not mean they will all be used in all use cases. For instance, AddUser in an authentication class may be defined in an interface, but not ever used in a website due to closed user sign up.
In general, the answer to the question of whether or not to use inheritance or an interface can be answered by thinking about it this way:
When thinking about hypothetical
implementing classes, is it a case
where these types are what I'm
describing, or is it a case where
these types can be or can do what I'm
describing?
Consider, for example, the IEnumerable<T> interface. The classes that implement IEnumerable<T> are all different classes. They can be an enumerable structure, but they're fundamentally something else (a List<T> or a Dictionary<TKey, TValue> or a query, etc.)
On the other hand, look at the System.IO.Stream class. While the classes that inherit from that abstract class are different (FileStream vs. NetworkStream, for example), they are both fundamentally streams--just different kinds. The stream functionality is at the core of what defines these types, versus just describing a portion of the type or a set of behaviors that they provide.
Often you'll find it beneficial to do both; define an interface that defines your behavior, then an abstract class that implements it and provides core functionality. This will allow you to, if appropriate, have the best of both worlds: an abstract class for inheriting from when the functionality is core, and an interface to implement when it isn't.
Also, bear in mind that it's still possible to provide some core functionality on an interface through the use of extension methods. While this doesn't, strictly speaking, put any actual instance code on the interface (since that's impossible), you can mimic it. This is how the LINQ-to-Objects query functions work on IEnumerable<T>, by way of the static Enumerable class that defines the extension methods used for querying generic IEnumerable<T> instances.
As a side note, you don't need to throw any NotImplementedExceptions. If you define a function or property as abstract, then you don't need to (and, in fact, cannot) provide a function body for it within the abstract class; the inheriting classes will be forced to provide a method body. They might throw such an exception, but that's not something you need to worry about (and is true of interfaces as well).
Personally, I think it depends on what the "type" is defining.
If you're defining a set of behaviors, I would recommend an interface.
If, on the other hand, the type really defines a "type", then I'd prefer an abstract class. I would recommend leaving the methods abstract instead of providing an empty behavior, though.
Note, even though all of these functions and such may be defined, it does not mean they will all be used in all use cases.
If this is true, you should consider breaking this up into multiple abstract classes or interfaces. Having "inappropriate" methods in the base class/interface really is a violation of the Liskov Substitution Principle, and a sign of a design flaw.
If you're not providing any implementation, then use an interface otherwise use an abstract class. If there are some methods that may not be implemented in subclasses, it might make sense to create an intermediate abstract class to do the legwork of throwing NotSupportedException or similar.
One advantage of abstract classes is that one can add to an abstract class new class members whose default implementation can be expressed in terms of existing class members, without breaking existing inheritors of that class. By contrast, if any new members are added to an interface, every implementation of that interface must be modified to add the necessary functionality.
It would be very nice if .net allowed for an interface to include default implementations for properties, methods, and events which did not make any use of object fields. From a technical standpoint, I would think such a thing could be accomplished without too much difficulty by having for each interface a list of default vtable entries which could be used with implementations that don't define all vtable slots. Unfortunately, nothing like that ability exists in .net.
Abstract classes should be used when you can provide a partial implementation. Use interfaces when you don't want to provide any implementation at all - just definition.
In your question, it sounds like there is no implementation, so go with an interface.
Also, rather than throwing NotImplementedException you should declare your method/property with the abstract keyword so that all inheritors have to provide an implementation.
#Earlz I think refering to this: Note, even though all of these functions and such may be defined, it does not mean they will all be used in all use cases. is directly related to the best way to 'attack' this problem.
What you should aim at is minimizing the number of such functions so that it becomes irrelavant (or at least not that important) if you use either or. So improve the design as much as you can and you will see that it really doesn't matter which way you go.
Better yet post a high level of what you are trying to do and let's see if we can come up together with something nice. More brains working towards a common goal will get a better answer/design.
Another pattern that works in some situations is to create a base class that is not abstract. Its has a set of public methods that define the API. Each of these calls a Protected method that is Overideable.
This allows the derived class to pick and choose what methods it needs to implement.
So for instance
public void AddUser(object user)
{
AddUserCore(user);
}
protected virtual void AddUserCore(object user)
{
//no implementation in base
}

How to design a inherited collection

I'm writing a program in C# that has a custom collection. The custom collection performs some useful aggregate functions (AllSuccessful, %Successful, etc) over it's members which are of type ResultInfo. I have several classes that derive from ResultInfo (UploadResultInfo, XUploadResultInfo, and YUploadResultInfo), and would like to have additional collections that inherit from ResultInfoCollection that have additional aggregate functions. The only problem with doing this as specified is that it leaves a useless
public void Add(ResultInfo item)
{
}
on the collection. Clarification: This method takes an argument of type ResultInfo, but a ResultInfo added to an UploadResultInfoCollection will throw an error. Is there an elegant way of solving my problem? I've considered generics but I don't quite know how that would work.
To define a generic class that handles any child of ResultInfo you just define it like
public class MyCollection<T> : ICollection<T>
where T : ResultInfo
{
... the required methods ... just use "T" instead of "ResultInfo" ...
public void Add(T item) {}
}
Later on you can use it by
MyCollection<FooResultInfo> coll = new MyCollection<FooResultInfo>();
Just try using them, they are not too difficult and learning by doing is the best way ...
I'm not sure how you are left with a useless Add method.
If the collection populates itself, you can make the Add method private.
If you want your "inherited" additional collections to not expose the Add method, use composition instead of inheritance.
Consider whether your useful methods actually need to be instance methods.
Do they need to maintain state when other operations happen or are they all possible using the publically avaialable (or internaally available) API?
If so then simply make them static methods (extension methods is probably a good idea) and don't worry about inheritance. If the methods are meaningful on IEnumerable<T> then so much the better, by doing this you make your utility functions vastly more usable and thus useful.
Using the resulting package of functions simply requires importing the relevant namespace.
If all you're doing is providing some extra methods to an otherwise existing collection type, then consider simply defining extension methods for that type and using a normal generic collection.

Collection<T> versus List<T> what should you use on your interfaces?

The code looks like below:
namespace Test
{
public interface IMyClass
{
List<IMyClass> GetList();
}
public class MyClass : IMyClass
{
public List<IMyClass> GetList()
{
return new List<IMyClass>();
}
}
}
When I Run Code Analysis i get the following recommendation.
Warning 3 CA1002 : Microsoft.Design : Change 'List' in 'IMyClass.GetList()' to use Collection, ReadOnlyCollection or KeyedCollection
How should I fix this and what is good practice here?
To answer the "why" part of the question as to why not List<T>, The reasons are future-proofing and API simplicity.
Future-proofing
List<T> is not designed to be easily extensible by subclassing it; it is designed to be fast for internal implementations. You'll notice the methods on it are not virtual and so cannot be overridden, and there are no hooks into its Add/Insert/Remove operations.
This means that if you need to alter the behavior of the collection in the future (e.g. to reject null objects that people try to add, or to perform additional work when this happens such as updating your class state) then you need to change the type of collection you return to one you can subclass, which will be a breaking interface change (of course changing the semantics of things like not allowing null may also be an interface change, but things like updating your internal class state would not be).
So by returning either a class that can be easily subclassed such as Collection<T> or an interface such as IList<T>, ICollection<T> or IEnumerable<T> you can change your internal implementation to be a different collection type to meet your needs, without breaking the code of consumers because it can still be returned as the type they are expecting.
API Simplicity
List<T> contains a lot of useful operations such as BinarySearch, Sort and so on. However if this is a collection you are exposing then it is likely that you control the semantics of the list, and not the consumers. So while your class internally may need these operations it is very unlikely that consumers of your class would want to (or even should) call them.
As such, by offering a simpler collection class or interface, you reduce the number of members that users of your API see, and make it easier for them to use.
I would personally declare it to return an interface rather than a concrete collection. If you really want list access, use IList<T>. Otherwise, consider ICollection<T> and IEnumerable<T>.
I don't think anyone has answered the "why" part yet... so here goes. The reason "why" you "should" use a Collection<T> instead of a List<T> is because if you expose a List<T>, then anyone who gets access to your object can modify the items in the list. Whereas Collection<T> is supposed to indicate that you are making your own "Add", "Remove", etc methods.
You likely don't need to worry about it, because you're probably coding the interface for yourself only (or maybe a few collegues). Here's another example that might make sense.
If you have a public array, ex:
public int[] MyIntegers { get; }
You would think that because there is only a "get" accessor that no-one can mess with the values, but that's not true. Anyone can change the values inside there just like this:
someObject.MyIngegers[3] = 12345;
Personally, I would just use List<T> in most cases. But if you are designing a class library that you are going to give out to random developers, and you need to rely on the state of the objects... then you'll want to make your own Collection and lock it down from there :)
It's mostly about abstracting your own implementations away instead of exposing the List object to be manipulated directly.
It's not good practice to let other objects (or people) modify the state of your objects directly. Think property getters/setters.
Collection -> For normal collection
ReadOnlyCollection -> For collections that shouldn't be modified
KeyedCollection -> When you want dictionaries instead.
How to fix it depends on what you want your class to do and the purpose of the GetList() method. Can you elaborate?
In these kind of case I usually try to expose the least amount of implemententation that is needed. If the consumers do not need to know that you are actually using a list then you don't need to return a list. By returning as Microsoft suggests a Collection you hide the fact that you are using a list from the consumers of your class and isolate them against an internal change.
Something to add though it's been a long time since this was asked.
When your list type derives from List<T> instead of Collection<T>, you cannot implement the protected virtual methods that Collection<T> implements.
What this means is that you derived type cannot respond in case any modifications are made to the list. This is because List<T> assumes you are aware when you add or remove items. Being able to response to notifications is an overhead and hence List<T> doesn't offer it.
In cases when external code has access to your collection, you may not be in control of when an item is being added or removed. Therefore Collection<T> provides a way to know when your list was modified.
I don't see any problem with returning something like
this.InternalData.Filter(crteria).ToList();
If I returned a disconnected copy of internal data, or detached result of a data query - I can safely return List<TItem> without exposing any of implementation details, and allow to use the returned data in the convenient way.
But this depends on what type of consumer I expect - if this is a something like data grid I prefer to return IEnumerable<TItem> which will be the copied list of items anyway in most cases :)
Well the Collection class is really just a wrapper class around other collections to hide their implementation details and other features. I reckon this has something to do with the property hiding coding pattern in object-oriented languages.
I think you shouldn't worry about it, but if you really want to please the code analysis tool, just do the following:
//using System.Collections.ObjectModel;
Collection<MyClass> myCollection = new Collection<MyClass>(myList);

Categories