A difference in style: IDictionary vs Dictionary

C#Java.NetInterface

C# Problem Overview


I have a friend who's just getting into .NET development after developing in Java for ages and, after looking at some of his code I notice that he's doing the following quite often:

IDictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

He's declaring dictionary as the Interface rather than the Class. Typically I would do the following:

Dictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

I'd only use the IDictionary interface when it's needed (say, for example to pass the dictionary to a method that accepts an IDictionary interface).

My question is: are there any merits to his way of doing things? Is this a common practice in Java?

C# Solutions


Solution 1 - C#

If IDictionary is a "more generic" type than Dictionary then it makes sense to use the more generic type in declaring variables. That way you don't have to care as much about the implementing class assigned to the variable and you can change the type easily in the future without having to change a lot of following code. For example, in Java it's often considered better to do

List<Integer> intList=new LinkedList<Integer>();

than it is to do

LinkedList<Integer> intList=new LinkedList<Integer>();

That way I'm sure all following code treats the list as a List and not a LinkedList, making it easy in the future to switch out LinkedList for Vector or any other class which implements List. I'd say this is common to Java and good programming in general.

Solution 2 - C#

This practice isn't just limited to Java.

It's often used in .NET as well when you want to de-couple the instance of the object from the class you're using. If you use the Interface rather than the Class, you can change the backing type whenever needed without breaking the rest of your code.

You'll also see this practice used heavily with dealing with IoC containers and instanciation using the Factory pattern.

Solution 3 - C#

Your friend is following the very useful principle:

"Abstract yourself from implementation details"

Solution 4 - C#

You should always attempt to program to the interface rather than the concrete class.

In Java or any other object oriented programming language.

In .NET world is common to use an I to indicate that is an interface what your're using. I think this is more common because in C# they don't have implements and extends to refer class vs interface inheritance.

I think whey would type

 class MyClass:ISome,Other,IMore 
 { 
 }

And you can tell ISome an IMore are interfaces while Other is a class

In Java there is no need for such a thing

 class MyClass extends Other implements Some, More {
 }

The concept still applies, you should try to code to the interface.

Solution 5 - C#

For local variables and private fields, which are already implementation details, it's better to use concrete types than interfaces for the declarations because the concrete classes offer a performance boost (direct dispatch is faster than virtual/interface dispatch). The JIT will also be able to more easily inline methods if you don't unnecessarily cast to interface types in the local implementation details. If an instance of a concrete type is returned from a method that returns an interface, the cast is automatic.

Solution 6 - C#

Most often, you see the interface type (IDictionary) used when the member is exposed to external code, whether that be outside the assembly or just outside the class. Typically, most developers use the concrete type internally to a class definition while they expose an encapsulated property using the interface type. In this way, they can leverage the concrete type's capabilities, but if they change the concrete type, the declaring class's interface doesn't need to change.

public class Widget
{
private Dictionary<string, string> map = new Dictionary<string, string>();
public IDictionary<string, string> Map
{
get { return map; }
}
}

later can become:

class SpecialMap<TKey, TValue> : IDictionary<TKey, TValue> { ... }

public class Widget { private SpecialMap<string, string> map = new SpecialMap<string, string>(); public IDictionary<string, string> Map { get { return map; } } }

without changing Widget's interface and having to change other code already using it.

Solution 7 - C#

As far as I've seen Java developers tend to use abstraction (and design patterns) more often than .NET developers. This seems another example of it: why declare the concrete class when he'll essentially only be working with the interface members?

Solution 8 - C#

IDictionary is an interface and Dictionary is a class.

Dictionary implements IDictionary.

That means that this is possible to refer to Dictionary instance with/by IDictionary instance and invoke most of the Dictionary methods and properties through IDictionary instance.

This is very recommended to use interfaces as many as possible, because interfaces abstracts the modules and assemblies of the applications, allows polymorphism, which is both very common and useful in many situations and cases and allows replacing one module by another without touching the other modules.

Suppose that in the present, the programmer wrote:

IDictionary<string> dictionary = new Dictionary<string>();

And now dictionary invokes the methods and properties of Dictionary<string>.

In the future the databases has been grown up in size and we find out that Dictionary<string> is too slow, so we want to replace Dictionary<string> by RedBlackTree<string>, which is faster.

So all what is needed to be done is replacing the above instruction to:

IDictionary<string> dictionary = new RedBlackTree<string>();

Of course that if RedBlackTree implements IDictionary then all the code of the application compiles successfully and you have a newer version of your application, where the application now performs faster and more efficient than the previous version.

Without interfaces, this replacement would be more difficult to do and would require the programmers and developers to change more code that is potential to bugs.

Solution 9 - C#

In the described situation almost every Java developer would use the interface to declare the variable. The way the Java collections are used is probably one of the best examples:

Map map = new HashMap();
List list = new ArrayList();

Guess it just accomplishes loose coupling in a lot of situations.

Solution 10 - C#

Java Collections include a multitude of implementations. Therefore, it's much easier for me to make use of

List<String> myList = new ArrayList<String>();

Then in the future when I realize I need "myList" to be thread safe to simply change this single line to

List<String> myList = new Vector<String>();

And change no other line of code. This includes getters/setters as well. If you look at the number of implementations of Map for example, you can imagine why this might be good practice. In other languages, where there is only a couple implementations for something (sorry, not a big .NET guy) but in Objective-C there is really only NSDictionary and NSMutableDictionary. So, it doesn't make as much sense.

Edit:

Failed to hit on one of my key points (just alluded to it with the getter/setters).

The above allows you to have:

public void setMyList(List<String> myList) {
    this.myList = myList;
}

And the client using this call need not worry about the underlying implementation. Using whatever object that conforms to the List interface that they may have.

Solution 11 - C#

Coming from a Java world, I agree that the "program to an interface" mantra is drilled into you. By programming to an interface, not an implementation, you make your methods more extensible to future needs.

Solution 12 - C#

I've found that for local variables it generally doesn't much matter whether you use the interface or the concrete class.

Unlike class members or method signatures, there is very little refactoring effort if you decide to change types, nor is the variable visible outside its usage site. In fact, when you use var to declare locals, you are not getting the interface type but rather the class type (unless you explicitly cast to the interface).

However, when declaring methods, class members, or interfaces, I think that it will save you quite a bit of headache to use the interface type up front, rather than coupling the public API to a specific class type.

Solution 13 - C#

Using interfaces means that "dictionary" in the following code might be any implementation of IDictionary.

Dictionary1 dictionary = new Dictionary1();
dictionary.operation1(); // if operation1 is implemented only in Dictionary1() this will fail for every other implementation

It's best seen when you hide the construction of the object:

IDictionary dictionary = DictionaryFactory.getDictionary(...);

Solution 14 - C#

I've encountered the same situation with a Java developer. He instantiates collections AND objects to their interface in the same way. For instance,

IAccount account = new Account();

Properties are always get/set as interfaces. This causes problems with serialization, which is explained very well here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionreinView Question on Stackoverflow
Solution 1 - C#ChrisView Answer on Stackoverflow
Solution 2 - C#Justin NiessnerView Answer on Stackoverflow
Solution 3 - C#Vitaliy LiptchinskyView Answer on Stackoverflow
Solution 4 - C#OscarRyzView Answer on Stackoverflow
Solution 5 - C#Sam HarwellView Answer on Stackoverflow
Solution 6 - C#Travis HesemanView Answer on Stackoverflow
Solution 7 - C#Gergely OroszView Answer on Stackoverflow
Solution 8 - C#user11336341View Answer on Stackoverflow
Solution 9 - C#NickDKView Answer on Stackoverflow
Solution 10 - C#MarkPowellView Answer on Stackoverflow
Solution 11 - C#AnjisanView Answer on Stackoverflow
Solution 12 - C#LBushkinView Answer on Stackoverflow
Solution 13 - C#Manrico CorazziView Answer on Stackoverflow
Solution 14 - C#Jim SchubertView Answer on Stackoverflow