Structural typing in C #

    When I studied the Go language, I really liked the idea of ​​casting to interfaces by method signatures (I did not like the rest of the type system, too primitive). This is a static duck typing! Scientific: structural typification .

    If you think about it, this approach has a lot of shortcomings: from the complexity of implementation to the violation of the Liskov substitution principle. Indeed, if a class has a method with the desired signature (including the name), this does not mean at all that this method does what is expected.
    Therefore, in mainstream languages, including C #, structural typing is not supported. It would seem that this and the fairy tale end. But recently, I realized that in the project that I am currently working on, structural typing is used. 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 A, B, and C auto properties. And a Calculator class that needs the value of property A to calculate something on its basis and put it in B. But he does not need to know about C. Also, he does not need to know about the DataItem class, because It can be used with other classes that have A and B.

    How to implement this? In advance, declare an interface for each of these properties, and mark each class with such properties as implementing the corresponding interfaces. And declare consumer class methods 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 data) where T: PropertyA, PropertyB{
        data.B = data.A > 0;
      }
    


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

    It’s more difficult to understand why this might come in handy, and whether the situation when a similar technique is needed is another smell of the code.

    Also popular now: