There are a couple of similar questions already on SO, but none of the ones I found really touches on this particular topic, so here it goes...
My understanding is that one should always attempt to return an interface over a concrete class. Won't go into the reasons behind it, plenty of things on SO about that already.
However in the case of an IReadOnlyCollection vs a ReadOnlyCollection I'm not sure if that rule should be followed.
An IReadOnlyCollection can be easily cast into a List, which... well... breaks the ReadOnly aspect that the contract promises.
ReadOnlyCollection however cannot be cast into a List, but it means returning a concrete class.
In the long run, does it actually matter? It seems to me like in most cases a ReadOnly*/IReadOnly* object is only returned returned by either a method or a read-only property.
So even if the user decides to cast it to something else (in the case of a IReadOnly* object) or use LINQ to create a collection of some kind out of it (in the case of ReadOnly* object), there's really no way that the class exposing the ReadOnly*/IReadOnly* object is going to accept that back.
So what's the recommendation here, return an IReadOnly* interface or a concrete ReadOnly* class instance?
IReadOnlyCollection<T> can only be cast to List<T> if the underlying object is of that type. ReadOnlyCollection<T> for example also implements IReadOnlyCollection<T>.
So my recommendation, return IReadOnlyCollection<T> and if you are worried that caller would wrongly cast it to something it shouldn't, make sure the underlying type is ReadOnlyCollection<T>
public IReadOnlyCollection<User> GetUsers()
{
return new ReadOnlyCollection<User>();
}
But returning IReadOnlyCollection<T> should be enough for caller of function to understand it is supposed to be read only. Note that you can never completely secure your code with a ReadOnlyCollection<T>, caller can still use reflection to access the internal list and manipulate it.
The only option in that case would be to create a copy if the list and return that.
You definitely should attempt to make your public methods return interfaces.
If you're afraid that your class's callers are going to cast and modify your internal structures, such as in this example, where a class's internal queue shouldn't be touched from the outside:
public class QueueThing
{
private List<QueueItem> _cantTouchThis;
public IReadOnlyCollection<QueueItem> GetQueue()
{
return _cantTouchThis;
}
}
Then you could use AsReadOnly() to return a new ReadOnlyList<T>, sourced from the private List<T>:
public class QueueThing
{
private List<QueueItem> _cantTouchThis;
public IReadOnlyCollection<QueueItem> GetQueue()
{
return _cantTouchThis.AsReadOnly();
}
}
Now the caller can cast the returned value all they want, they won't be able to modify the _cantTouchThis member (except of course when they're going to use reflection, but then all bets are off anyway).
Given many types can implement an interface, a user of such a method should definitely not assume that it's safe to cast the return value of the method to any concrete type.
Microsoft's guidelines here state:
✓ DO use ReadOnlyCollection, a subclass of ReadOnlyCollection<T>, or in rare cases IEnumerable<T> for properties or return values representing read-only collections.
So, basically, you should return ReadOnlyCollection<T>. It specifies interface IEnumerable in other cases, so if it intended interface IReadOnlyCollection<T>, it would have stated so.
Related
I've seen Returning 'IList' vs 'ICollection' vs 'Collection' and the other questions that it links to, but I'm still confused about this issue.
Let's assume for demonstration purposes that I have a class, where I expose a public method, as follows:
public ReadOnlyCollection<Type> GetReadOnlyCollection(IEnumerable<Type> enumerable)
{
List<Type> list = enumerable.ToList();
return new ReadOnlyCollection<Type>(list);
}
To follow CA1002, should my method return the actual collection classes (ReadOnlyCollection, Collection, etc.) or their interfaces (IList, ICollection, etc.) if I wish to return a ReadOnlyCollection specifically?
You gain flexibility to later change the implementation if you return a type as general as possible. But of course you have to return a type that is useful for the consumer. Hence, generally returning the interface type is better, and the more general type as well, as long as this does not cause any problems in usage on consumer side.
My original question was not super well-defined; there are a number of considerations that should be taken into account:
Does the user only need to enumerate through the code? If so, IEnumerable is probably enough.
Should the user know that the collection is intended to be read-only? If so, IReadOnlyCollection is probably fine.
Do you want to prevent the user from casting your read-only collection to a mutable type? If so, use an immutable collection from System.Collections.Immutable.
Some useful answers are in these questions:
ReadOnlyCollection or IEnumerable for exposing member collections?
IEnumerable vs IReadonlyCollection vs ReadonlyCollection for exposing a list member
I have a generic class that implements IList
public class ListBase<T>: IList<T>, IListBase{
IEnumerator<T> GetEnumerator(){ ....
System.Collections.IEnumerator GetEnumerator(){ return GetEnumerator();}
}
The IListBase is an interface I use to access methods on this class for cases where I don't know the type of T at runtime.
I need to implement a second Enumerator via this IListBase interface which will iterate the members of my class and return them cast as a base type that all members will implement.
I've tried having the IListBase implement my specific Enumerator:
public interface IListBase: IEnumerable<MemberBaseType> { ....
But this blows up due to the fact that T and MemberBaseType could be the same in some instances. Even adding the enumerator members to the interface and then using explicit declarations doesnt help this problem.
I then tried adding another method to call for just getting specific IEnumerator, but the compiler then complains about not finding a public GetEnumerator method to use with this type...
Any recommendations for adding this secondary enumerator so they don't collide with each other?
Having two enumerators at the same level that do different things is (IMO) a bad idea. You can probably force it, but as soon as someone casts your type (especially if casting to the non-generic interface) it is largely guesswork which they will get.
I would recommend (instead) making this available via a property, for example .Members, where .Members offers this enumeration. Then no ambiguity of intent, and no compiler unhappiness. So I could use:
foreach(var member in list.Members) { /* add columns */ }
foreach(var item in list) { /* add rows */ }
You might also consider ITypedList, which may have some relevence here, especially if you want to data-bind to your list (this isn't necessary if T by itself defines everything cleanly).
In short:
public interface IListBase {
IEnumerable<MemberBaseType> Members {get;}
}
I am asking this because it seems like using Object seems to be an easy way out to solve certain problems, like "I don't have a specific type, so use Object", etc.
Also the reason this made me curious is because a colleague of mine told me that if .NET was a true object-oriented platform then it wouldn't have to have a catch all type like Object.
So if .NET didn't have the Object type, what would be the alternative ways to solve the occuring problems to make it function just the same?
Also just to note, this is not to bash .NET, as I use it daily in my work. Just want to know more about it.
EDIT: Another note I remembered is because the type Object exists, its effect ripples throughout the whole .NET. Like IEnumerable exists but also IEnumerable<T>. And in many situations you have to implement both the generic and non-generic version of things, etc.
I would say that the problem that is solved by Object is not "I don't have a specific type, so use Object", but rather "I don't really care what type this is; all I need to know it that it is an Object"
It is a convenience, not only for use as a 'generic' type but also for reflection, garbage collection etc.
Other languages (C++) can do without, but I would hesitate to say that makes those languages more OOP.
Your friend probably works with a dynamic language (like ruby or python), right?
There are a great many people who think that strongly typed languages should be referred to as "class oriented" rather then "object oriented", because all possible behaviors and polymorphism needs to be done up front in the class definition. When your method accepts anything, any any checks are done based off of the objects capabilities rather then its class, you could say that is a more object oriented approach.
I am sort of conflicted on this argument. There is this boneheaded belief in programming circles that OO is unequivocally Good, no matter what the problem or requirements. Because of that, people tend to try to win arguments by saying "such and such isn't object oriented", and since object oriented is a synonym for good, they win. Even though I think static languages are a pain to work with, I think calling them not OO is a disingenuous way to make your point. On the other hand, anything that will make a programmer reach outside his comfort zone and learn a new way to do something (if for no other reason then to win an argument) can't be totally bad. As I said, conflicted. :)
Remember that inheritance denotes an "is-a" relationship. Every class in .NET "is a(n)" object. They all have a ToString method. They all have a type, which you access through GetType. This sort of relationship and the resultant sharing of functionality is the basis of object-oriented programming.
In a strongly-typed framework, Objects have to start somewhere.
The type object is not there to provide an "easy" catch-all casting option, or to force you to cast down to the lowest common denominator. It is there to provide the absolute most general case for an object- a basis for reference comparison and a handy ToString() method, among a few others.
Yes object type can be misused, but it provides seminal functionality to the world of .NET (above all IMO is GetType()). So if there is a problem, it is not with having the type of object.
Alternatives are many, including Generics and OOP practices such as interfaces...
If the object derivation hierarchy didn't have a single unified head, then it would be impossible to test for equality between any two arbitrary...uh...things without resorting to dynamic typing.
Other than that, I suspect the functionality of object could have been handled just about as well by separate interfaces (IEqualable and IConvertableToString). On the other hand, object's virtual methods are pretty handy sometimes, especially ToString, which can be used by an IDE or debugger when displaying program state. It's really a pragmatic design.
I'm by no means particularly knowledgeable on this subject, but from my perspective it was useful to allow people to build polymorphic components without having prior knowledge of how those components would be consumed. What do I mean by that? Let me try to explain.
Let's take a simple example with the .NET framework's ArrayList class. This was part of the original framework, before Generics were introduced. The authors of the ArrayList class were trying to provide a useful dynamic list implementation, but they had no way of knowing what kinds of objects would be inserted into the list. They used the Object type to represent the items in the list because it would allow any type of class to be added to the list. For example:
ArrayList people = new ArrayList();
people.Add(new Doctor());
people.Add(new Lawyer());
people.Add(new PetDetective());
people.Add(new Ferrari()); // Yikes!
// ...
for (int i = 0; i < people.Count; i++)
{
object person = people[0];
// ...
}
Now, if this were your own application and you knew that your Doctor, Lawyer, and PetDetective classes all derived from a common Person base class, then you could, in theory, build your own linked list implementation based on the Person class rather than the Object class. However, that's a lot of extra work for very little benefit when you already have a built and tested ArrayList class. If you really want to make it specific to your Person base class, then you could always create a wrapper class for ArrayList that only accepts Person-derived objects.
In C++, you could do essentially the same thing using the "void pointer" data type (void*). However, C++ also supported templates (very similar to generics), which made it much easier to build a useful component without knowing the details of what other classes it would be used with. Since C# did not initally support generics, using the Object type was really the only way to build general polymorphic components for other people to use.
The idea that the concept of System.Object could be replaced by interfaces that, as a rule, all classes implement has been mentioned a few times on this question. While I think the idea is valid, in the end I would say that it doesn't buy you anything. Even if such interfaces existed, the question would still remain of how the compiler would actually ensure that classes implemented those interfaces.
Below is some example code where I try to explore a hypothetical situation where there is no System.Object type and how the implementation under the hood as well as usage of those interfaces might look.
// let's start off by defining interfaces to describe the various methods that are currently available from the System.Object class
public interface IEquatable
{
bool Equals(IEquatable other);
}
public interface IHashCodeGenerator
{
int GetHashCode();
}
public interface ITypeIdentifiable
{
Type GetType();
}
public interface IConvertibleToString
{
string ToString();
}
// This guy throws a wrench into things, because we can't privately (or "protectedly") implement an interface.
// This is discussed further below on the MyClass.MemberwiseClone method.
public interface IMemberwiseCloneable
{
}
// This class simply encapsulates similar functionality found within the System.Object class
public static class ClrInternals
{
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool Equals(IEquatable objA, IEquatable objB);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int GetHashCode(IHashCodeGenerator hashGenerator);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Type GetType(ITypeIdentifiable typedInstance);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern IMemberwiseCloneable MemberwiseClone(IMemberwiseCloneable original);
}
// let's say that as a rule the compiler implicitly makes all classes implement these interfaces
class MyClassExampleA : IEquatable, IHashCodeGenerator, ITypeIdentifiable, IConvertibleToString, IMemberwiseCloneable
{
// The compiler also implicitly makes all classes implement the interfaces with the following code (unless otherwise specified)
#region IEquatable Members
public bool Equals(IEquatable other)
{
// let's suppose that this is equivalent to the current implementation of Object.Equals
return ClrInternals.Equals(this, other);
}
#endregion
#region IHashCodeGenerator Members
public int GetHashCode()
{
// let's suppose that this is equivalent to the current implementation of Object.GetHashCode
return ClrInternals.GetHashCode(this);
}
#endregion
#region ITypeIdentifiable Members
public Type GetType()
{
// let's suppose that this is equivalent to the current implementation of Object.GetType
return ClrInternals.GetType(this);
}
#endregion
#region IConvertibleToString Members
public string ToString()
{
// let's suppose that this is equivalent to the current implementation of Object.ToString
return this.GetType().ToString();
}
#endregion
// this one is perhaps a little goofy, since it doesn't satisfy any interface
// In order to be equivalent to the current Object.MemberwiseClone implementation, I've made this protected,
// but we cannot have a protected method that implements an interface, so this throws a wrench into things.
protected MyClassExampleA MemberwiseClone()
{
// let's suppose that this is equivalent ot the current implementation of Object.MemberwiseClone
return (MyClassExampleA)ClrInternals.MemberwiseClone(this);
}
// ** All of the above code is just a representation of the implicit semantics that the compiler/CLR applies to a class. Perhaps this code is not actually generated by the compiler for each class (that would be a lot of duplication!), but rather the CLR might handle this logic internally
}
// Ok, so now I'm implementing a general Stack class
public class Stack
{
// what type should I use for the parameter?
// I have five different interfaces to choose from that I know all classes implement, but which one should I pick?
public void Push(type??? item)
{
// ...
}
// what type should I use for the return type?
// I have five interfaces to choose from, but if I return one,
// then my caller can't utilize the methods defined in the other interfaces without casting.
// I know all classes implement all five interfaces, but is it possible that my Stack might also contain non-class objects that don't implement all interfaces? In that case it might be dangerous for the caller to cast the return value from one interface to another.
public type??? Pop()
{
// ...
}
// In C++ I could have used void* or defined the Stack class as a template
}
// moving on...
class StackUtilizer
{
// here I try to utilize the Stack class
public void UseStack(Stack stack)
{
// what type should I use for the variable to hold the result of the Stack.Pop method?
type??? item = stack.Pop();
// if I use IEquatable
IEquatable item1 = stack.Pop();
IEquatable item2 = stack.Pop();
item1.Equals(item2); // then I can do this
Type itemType = item1.GetType(); // but I can't do this
string s = item1.ToString(); // nor can I do this
// Ok, this calls for another interface that composes all of these other interfaces into one
}
}
// let's define a single interface that pulls all of these other interfaces together
public interface IObject : IEquatable, IHashCodeGenerator, ITypeIdentifiable, IConvertibleToString, IMemberwiseCloneable
{
// no need to define any methods on this interface. The purpose of this interface is merely to consolidate all of these other basic interfaces together.
}
// now we change the compiler rule to say that all classes implicitly implement the IObject interface
class MyClassExampleB : IObject
{
// ... <refer to MyClassExampleA for the implicit implementation of the interfaces>
}
// now let's try implementing that Stack class again
public class Stack
{
// I know that all classes implement the IObject interface, so it is an acceptable type to use as a parameter
public void Push(IObject item)
{
// ...
}
// again, since all classes implement IObject, I can use it as the return type
public IObject Pop()
{
// ...
throw new NotImplementedException("This is an example. The implementation of this method is irrelevant.");
}
}
class StackUtilizer
{
// here I try to utilize the Stack class
public void UseStack(Stack stack)
{
// now I can just use IObject for my variables holding the return value of the Stack.Pop method
IObject item = stack.Pop();
// if I use IObject
IObject item1 = stack.Pop();
IObject item2 = stack.Pop();
item1.Equals(item2); // then I can do this
Type itemType = item1.GetType(); // and I can do this
string s = item1.ToString(); // and I can do this
}
}
So, in the end we still have an IObject interface, similar to the current System.Object class. The open question is how the compiler/CLR would handle enforcing our rule that all classes implement the IObject interface.
I can think of three possible approaches:
The compiler generates the implicit interface implementation for each class, which would cause a lot of duplication.
The CLR would handle those interface implementations in a special way that would not require the compiler to actually generate code for each class.
We define a base class, let's call it Object (starting to sound familiar?), that implements the IObject interface and we change the rule to say that all classes implicitly inherit from Object (this is exactly what we have today but without the interfaces).
What is the need of IDictionary interface. How can IDictionary interface be initialized. After all it is just an interface. The following code snippet is from msdn. I could not understand it.
IDictionary<string, string> openWith = new Dictionary<string, string>();
It defines the important functions that an Dictionary should implement.
The line from MSDN means that you are creating an object openWith which implements the functions (methods) defined in IDictionary interface.
When you use Dictionary to declare the variable like:
Dictionary<string,string> openWith=.....;
you are bind with the concrete type of object. But when you use
IDictionary<string,string> openWith=....;
you can use it with any object that implements IDictionary interface, maybe your own custom class :)
The whole point of interfaces is to provide... well, an interface to whatever module (I use "module" in a broad sense here) so that calling code will not have to worry about how this particular interface is implemented.
As for "How can IDictionary interface be initialized", this is technically not correct. What can be initialized is a variable, whose type is IDictionary<T, V>. Sure enough variables have to be initialized, but that's usually hidden from the "client code".
IDictionary is not very representative, however. Rather, consider an IDataReader interface. You've surely dealt with ADO.NET, so this should look familiar:
public Foo PopulateFromDataReader(SqlDataReader dataReader)
This particular method is tightly coupled to an SqlDataReader, so you'd have to rewrite it for it to support, say, Access or Oracle or MySQL or Firebird or whatever. In other words, you depend on implementation.
Now consider:
public Foo PopulateFromDataReader(IDataReader dataReader)
This method can be used with whatever class that implements IDataReader, which means with basically any ADO.NET-compatible data provider.
It would be no different to any other interface. Try thinking about a simpler example:
interface IThermometer
{
double CurrentTemperature { get; }
}
Now we have a way to get the temperature, though we don't care exactly how it's measured. We can create various implementations:
class MercuryThermometer : IThermometer
{
public double CurrentTemperature
{
get { return ... /* gets the temperature somehow */ }
}
}
The rest of the program doesn't need to know which thermometer it's using.
I suspect you've simply overlooked the difference between the variable typed as IDictionary<,> (the interface), and the value (reference) initialized as a Dictionary<,> (note no I; the concrete type).
It's also useful for unit testing. You can write a unit test for a method that accepts an IDictionary instead of a Dictionary and pass a mock. If it were to accept a class instance (which could also be sealed) you'd be a little screwed (you'd have to use the adapter pattern and so on).
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);