📜 ⬆️ ⬇️

Structural Typing in C #

When I studied Go, I really liked the idea of ​​bringing to interfaces by method signatures (I didn’t like the rest of the type system, it’s too primitive). This is a static duck typing! Scientifically: structural typing .

If you think about it, this approach has a lot of flaws: starting with the complexity of implementation and ending with a violation of the Liskov substitution principle. After all, if a class has a method with the required signature (including the name), this does not at all mean that this method does what is expected.
Therefore, in mainstream languages, including C #, structural typing is not supported. It would seem on this tale and the end. But recently, I realized that in a project that I am doing now, structural typing is applied. Details under the cut.

In the project, the method is used to work with getters / setters. Of course, it can also be used for conventional methods, but this is unlikely to give anything good.

So. Imagine that you have a set of classes that have many of the same properties (name and type).
And even more classes that need data from these properties to work. For example: there is a DataItem class with autoproperties A, B, and C. And the Calculator class, which needs the value of property A, to base something on it and put it into B. And you don’t need to know about C. Nor does he need to know about the DataItem class, since It can be used with other classes that have A and B.
')
How to implement it? Announce for each of these properties, the interface, and each class with such properties, mark as implementing the corresponding interfaces. And methods of classes of consumers to declare generic.

Implementation:

interface PropertyA{ int A {get; set;} } class DataItem: PropertyA, PropertyB, PropertyC{ public int A {get; set;} public bool B {get; set;} public string C {get; set;} } ... void Calculate<T>(T data) where T: PropertyA, PropertyB{ data.B = data.A > 0; } 


It's simple: by specifying the limitations of a generic parameter, you can assemble a suitable set of fields, and the object of any class that implements them can be transferred to such a method without any ghosts.

It’s harder to understand why this might be useful, and whether there is a situation when such a technique is needed is another smell of code.

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


All Articles