Closed qwertie closed 5 years ago
The current (D#) implementation actually compiles singleton classes slightly differently: all non-private
singleton methods are converted to instance methods. So something like
public static class Foo : IBar, IBaz
{
public static int Bar() { /* implementation */ };
public static int Baz() { /* implementation */ };
public static double F() { /* implementation */ };
}
actually gets converted to:
public class Foo : IBar, IBaz
{
// Interface implementation
public int Bar() { /* implementation */ };
// Interface implementation
public int Baz() { /* implementation */ };
// Not an interface implementation.
public double F() { /* implementation */ };
private Foo() {}
private static Foo __instance__;
public static Foo Instance { get { return __instance__ = __instance__ ?? new Foo(); } }
}
Note that D# interprets Foo
, as in Foo.Bar()
, as syntactic sugar for Foo.Instance
. So Foo.Bar()
becomes Foo.Instance.Bar()
. The advantage of this approach is that there are no "thunk" functions. This reduces code size somewhat, and, more importantly, it eliminates a hard-to-optimize layer of indirection: I don't think the JIT optimizes vtable entries to eliminate those thunks. Furthermore, accessing Foo
in Foo
does not require a call to Instance
, as Instance
corresponds to the this
pointer.
I suppose there are disadvantages to this approach, as well, like passing a this
pointer around when not strictly necessary.
Those static
extension methods do seem useful. Perhaps they could even be used to create mixin interfaces?
Yes, I understood your explanation before about how static
essentially just disappears from the function declarations. I don't think that's the right approach, though. Mainly because it's not backward compatible with C#, unless the implementation does something really weird - switching static
members to non-static as soon as you implement an interface. Remember, EC# is supposed to be 99.9% backward compatible. Breaking changes should be avoided, and when present, rare and minor.
Mixin interfaces? What do you mean?
it's not backward compatible with C#
Do you have a reflection scenario in mind? If so, then I completely agree. But maybe singletons warrant a different type specifier, like Scala's object
. I modified static class
semantics for D#, but, in hindsight, that didn't always work out the way I wanted it to. A separate keyword would also avoid breaking changes.
Mixin interfaces? What do you mean?
Extension methods have always been most useful to me when used on interfaces. So I think it'd be great if we could write something along the lines of:
public interface IExpression
{
/// <summary>
/// Tests if this expression node has no side-effects.
/// Its children can still have side-effects, though.
/// </summary>
bool IsConstantNode { get; }
/// <summary>
/// Applies the given visitor to this expression's children.
/// </summary>
IExpression Accept(INodeVisitor Visitor);
/// <summary>
/// Tests if this expression tree has no side-effects.
/// This means that both this expression node and its children
/// have no side-effects.
/// </summary>
public static bool IsConstant(this IExpression Expr)
{
// Visit the expression, make sure that all of its children are
// also constant.
}
}
Extension properties would also be tremendously helpful here.
I did not, no - although that's a good point. So if you're asking how it's not backward compatible:
static
members won't find the ostensibly static members.It looks like my original proposal was incomplete, so I edited it. Search this page for Foo_ext
to find it.
About the second thing, let's call it "extension methods in interfaces". I like it. It could be implemented the same way, by adding an _ext
class to hold extension methods. What I want even more is default interface implementations - but that's harder. It requires a technique to store default implementations in an assembly such that they can be consumed by other assemblies.
Continuing from #26, It seems to me that the obvious way to support interfaces that include static members is like this:
For convertibility to C#, a
static class
likecould be implemented either by removing
static
, so that a constructor and interfaces are allowed, or by doing this harder thing:I'm not sure what you meant about lexical macros, but this cannot be done with a lexical macro since the macro can't tell which methods are members of an interface.
Removing
static
fromstatic class
is a problem unfortunately, because C# only allows extension methods in static classes, and there's no logical reason not to allow a static class to contain both extension methods and interface implementations. On the other hand, maybe we could flip it around and move the extension methods to a new class if necessary. In fact, yes, I like it. I've often wanted to define an extension method inside a non-static class and this would be possible like so:Note: I just verified that plain C# allows
using static Foo
whereFoo
is not a static class.