📜 ⬆️ ⬇️

Interfaces in C #

For those who are just starting to master C #, the question often arises of what an interface is and why it is needed.

First about what can be found on the first link in a search engine. In most articles, the meaning of the interface is explained as a “contract” on what the class should contain, what properties and methods. For example, we have an interface:

public interface IForecast { int GetForecast(int value); int Size { get; set; } } 

')
Accordingly, if a class implements this interface, then it must contain the implementation of the int method GetForecast (int value) and the Size property.

The practical value of such a contract is minimal. If you throw the interface out of the project, everything will work fine without it. Unless you want to completely rewrite the logic of the class and then the interface will help you not to forget about the necessary methods.

Summing up this part, if an interface is implemented only in a single class, then do not waste time on it. He just does not need.



Addition
Immediately after the publication, a lot of criticism fell on me, at first I tried to answer, but then I realized that there was no point. All critics rest on what I wrote in the previous paragraph and try to give complex examples of projects where there are many classes, all sorts of links here and there, support by the team and so on. I probably was wrong, that I briefly summarized the introduction. But the bottom line is that the interface is not always needed. If you have your own personal (or just not very large) project that does not plan to scale, which no one refers to and, most importantly, that works successfully , then the introduction to the project of interfaces will not change anything. And do not invent stories that somewhere someone once implemented the interface and gained immortality. If the interface were needed everywhere, it would be an integral part of the class.

This article is about how you can use the interface not for connectivity between projects, but within a single project. On this occasion, criticism has not yet been.

End of Supplement

Fortunately, the interface capabilities are much more interesting. The interface can set a common feature for disparate objects, and this opens up tremendous opportunities in terms of code flexibility.

For example, suppose we have two classes:

 class First 
and
 class Second 


These are two completely different classes, but let them have something in common, i.e. we want one method to work with both of them without additional logic. In this case, we can implement a common interface, i.e. declare these classes as

 class First : IForecast 
and
 class Second : IForecast 


Now we can make a common method for them:

 void AnyMethod(IForecast anyClass) { var value = anyClass.GetForecast(10); } 


As you can see, the value variable will receive the value of the GetForecast function from the class that will be passed as a parameter without additional actions on type casting, etc.

Another example, we do not know in advance which class we will need in the course of computations, however we need to declare an instance of this class before starting work. In this case, you can declare an instance of the class that implements the interface:

 ... IForecast any; …  : if(...) any = new First(); else any = new Second(); 


You can go even further and declare an array (or list) of such objects:

 var array = new IForecast[2]; array[0] = new First(); array[1] = new Second(); 


And then you can, for example, calculate the sum of all Size properties:

 var summ = 0; foreach (var forecast in array) { summ += forecast.Size; } 


An interface declaration has one drawback: you will only have access to methods and properties declared in the interface and the class itself . If your class is inherited from the base class, then to access its methods you will have to do a type conversion:

 public class BaseClass { public int GetValue(int value) { return value * 2; } } public class Second: BaseClass, IForecast IForecast frc; frc = new Second(); var frcBase = (BaseClass) frc; var result = frcBase.GetValue(45); 


Another focus with interfaces can be cranked using the ability to implement two interfaces in the same class with the same signature but different content methods. I don’t know what practical use this may be other than the one already mentioned, but if suddenly you don’t have enough imagination to come up with the names of functions, you can put them into the interfaces.

For example, add another interface to our project:

 public interface IForecast2 { int GetForecast(int value); } 


And create a new class that inherits both interfaces:

 public class Third: IForecast, IForecast2 { int IForecast.GetForecast(int value) { return value + Size; } public int Size { get; set; } int IForecast2.GetForecast(int value) { return 2 * value + Size; } } 


This is called an explicit interface implementation. Now you can build this structure:

  var third = new Third {Size = 10}; var v1 = ((IForecast) third).GetForecast(100); var v2 = ((IForecast2)third).GetForecast(100); Console.WriteLine(v1+v2); 


Interestingly, when implementing such interfaces, access modifiers (“public” or something else) cannot be assigned to methods, but they are quite accessible as public via type conversion.

As you can see, it works, but it looks too cumbersome. To somehow improve the code, you can write a little differently:

 var third = new Third {Size = 10}; var bad = (IForecast) third; var good = (IForecast2) third; var v1 = bad.GetForecast(100); var v2 = good.GetForecast(100); Console.WriteLine(v1+v2) 
;

bad and good will refer to the third, but keep in mind the different interfaces. The ghost can be done once, and its result can then be used repeatedly. It is possible that in some cases this will make the code more readable.

Another interface application is the rapid fabrication of plugs for functions.
For example, you build a large project in a team and your class depends on the class that your colleague writes. But not yet written. The wise chief prepared the interfaces of all the main classes at the first stage of the project development and you can no longer wait for a colleague, but implement a stub class for your class. Those. the temporary class will not contain logic, but will only pretend that it works: accept calls and return adequate values. To do this, you only need to implement the same interface that your colleague received.

A working project with all the examples from this article can be found here: link

Source: https://habr.com/ru/post/343852/


All Articles