Power3: Shared methods inside interfaces


[This post is part of a series, “wish-list for future versions of VB“]


 


IDEA: Allow shared methods inside interfaces, including operators. To support this we’d also need changes inside the CLR.


SCENARIO: You want to write a general-purpose mathematical algorithm that operates upon any numeric type. You’d like to write it like this:


Interface INumeric


    Shared Operator +(ByVal x As INumeric, ByVal y As INumeric) As INumeric


End Interface


 


Class Integer : Implements INumeric


End Class


 


Class Double : Implements INumeric


End Class


 


Function FourierTransform(Of T As INumeric)(ByVal x As T()) As T()


    ‘ …


End Function


The current workaround is that you have to provide several different versions of your function, one for each numeric type that you want it to work upon.


 


SCENARIO: Template meta-programming. I have a hunch that shared methods in interfaces would open up a whole new world of programming, not as powerful as C++ template meta-programming, but getting close. This is just a hunch so far. If you can think of powerful subversive uses of shared methods in interfaces, please write in!


 


Note that the “generic numeric library” doesn’t seem particularly compelling. That’s because maths libraries like this are supposed to be super-fast, and the JIT can do a better job of optimizing if it’s given specialized versions of each function.


 


Provisional evaluation from VB team: We do not think this idea is worth pursuing. (As always, we’re open to persuasion if you come up with a nicer design or more compelling scenarios!)

Comments (2)

  1. Dzonny says:

    Shared methods are supported in interfaces by CLR (see Partition I, §8.9.4):

    "An interface type definition can define and implement static methods (see §8.4.3) since static methods are associated with the interface type itself rather than with any value of the type. Interfaces can have static or virtual methods, but shall not have instance methods."

    CLS rule 19 tells that static methods in interfaces are not CLS-compliant: "CLS-compliant interfaces shall not define static methods, nor shall they define fields."

    There’s no special semantic CLR adds to static methods in interfaces. They are simply there and can be called. Thats all. And I don’t see anything special about static methods in interfaces. Having static method in interface is as useful as having static method in class (i.e. very useful) but nothing special. This way we can also define operator in the interface taking interface instance as its parameter(s).

    What I think is much more useful is way how to force class implementing the interface to have some operator. This can be achieved 2 ways (both of which requires changes in CLR and/or CLS). What we usually need is to apply operator on two values of same type not on two interfaces. We need to establish special pseudo types meaning actual interface implementation.

    1) Operators as instance methods

    Interface INumber

       Operator+(other As Me) As Me

    End Interface

    Structure Int32 : Implements INumber

       Private Function Add(other As Int32) As Int32 Implements INumber.Operator+

           Return Me + other

       End Function

    End Structure

    2) Required implementing class to implement certain static method

    Interface INumber

       Shared Operator+(a As Me, b As Me) As Me

    End Interface

    Structure Int32 : Implements INumber

       Private Shared Function Add(a As Int32, b As Int32) As Int32

           Return a + b

       End Function

    End Structure

    It will then be possible:

    Class Sumarizer(Of T As {INumber, Structure})

       Private _sum As T

       Public ReadOnly Property Sum() As T

           Get

               Return _sum

           End Get

       End Property

       Public Sub Add(ByVal value As T)

           _sum += value

       End Sub

    End Clas

    But it will not be possible:

    Dim a As INumber = 7

    Dim b As INumber = 9

    Dim c = a + b

  2. Kevin Ryall says:

    We can achieve a lot of this already by using extension functions, but only for functions and not for operators unfortunately. I already this technique quite a lot to add functionality to interfaces and reduce the burden on implementing classes…

    Having to use modules for declaring extension functions is a pain though – it would be much more encapsulated if we could declare them in the interface instead of adding a module in the same file. There’s no logical reason why this wouldn’t make sense.

    The real pain with using modules is that they are globally visible and can be used everywhere without qualification – this leads to less understandable / moveable code, and has lead us to ban the use of modules in almost all cases. Don’t get me wrong – the automatic global import is useful is some cases – we use a global validation / assertion module that is simpler without importing or qualifying – but it is not appropriate most other cases. What I’d really like is a way to prevent the global importing on specific modules – either by adding the static class syntax from C#, or more likely, by adding a custom attribute that would prevent it. I actually though I’d found this recently when I discovered the HideModuleName attribute, but it does something completely different (almost the opposite). What I’d like is an attribute called SuppressGlobalImports or similar – this would go a long way to making modules actually useful, whereas at the moment they’re not worth using in almost all cases.