Partial Methods and C# 3.0


Z

Zach

I was reading about partial methods in the upcoming C# 3.0 with a
friends and we were having a discussion about their usefulness.

One on hand, they seem to be ok at providing a solution for allowing a
class to be extended at compile time by users of the class, and as
pointed out in some articles and papers they are good at acting as
lightweight event handlers.

On the other hand, they are in my eyes exactly almost a strict subset
of the delegate/event model already provided by C# and the .NET
framework.

The idea is that you can do something like this:

partial class Foo
{
partial void SomeEventHandler(int i);

int VeryExpensiveMethod() { ... }

public void Method()
{
SomeEventHandler(VeryExpensiveMethod());
}
}

Now, this code would exist in a library somewhere and a user of the
library would simply type the following code:

partial class Foo
{
partial void SomeEventHandler(int i) {/* Do something with i */}
}

If that code is not present, then Foo.Method() would essentially
compile down to an completely empty method. The advantage over using
the standard Strategy design pattern (e.g. virtual methods) is that
VeryExpensiveMethod() will be compiled out since all this information
is known at compile time.

But the advantage over using the delegate/event model is minimal, and
almost non-existant. Consider if the class had been written like
this:

class Foo
{
public void delegate SomeEventHandler(int i);
public event SomeEventHandler OnSomeEvent;

int VeryExpensiveMethod() { ... }

public void Method()
{
if (OnSomeEvent != null)
OnSomeEvent(VeryExpensiveMethod());
}
}

This is almost equivalent, the only obvious difference being that in
the case of the delegate/event, OnSomeEvent will always be checked for
null, and the method will never compile down to an empty method.


But... Have they really designed an entire language feature and
keyword usage around one micro-optimization? The latter is actually
more maintainable and clearer IMO, and definitely more flexible. The
only price is that you have to suffer a single null pointer
comparison, as well as any overhead incurred by the Delegate or
MulticastDelegate classes for the actual dispatch.


Am I missing something here? Is there some elegant design pattern
that this can be used with? Partial -classes- actually solved a real
problem, in particular that generated classes could not be customized
in such a way that re-generating the code would not interfere with the
customizations.

But partial methods seem to solve nothing unless you're writing
extremely performance intensive code, in which case I would argue that
maybe you shouldn't be using C# in the first place.

Thoughts?
 
Ad

Advertisements

M

Marc Gravell

Forgetting best-practice about listening to your own events (or
rather: not), how (when?) would you ever subscribe to your own events
if the constructor you are interested in is in the generated part of
the class? You can't override your own methods, for instance.

Also - in what way more maintainable? You've had to introduce a lot of
extra fluff (a delegate declaration, an event declaration, an event
reference in every instance [ok, you could use EventHandlerList here],
the null-check, etc). And of course some ctor mangling to subscribe.
Now (taking sqlmetal classes as an example) multiply this by twice the
property count (both in the setter, one pre, one post) plus a few
extras. That is a *lot* of maintenance.

The partial method is by comparison and IMO much cleaner. And when you
don't implement something it simply evaporates; no effort.

Marc
 
Ad

Advertisements

J

Jon Skeet [C# MVP]

But partial methods seem to solve nothing unless you're writing
extremely performance intensive code, in which case I would argue that
maybe you shouldn't be using C# in the first place.

1) With partial methods you don't need a compatible delegate type. The
Func<> and Action<> delegates are present, but don't cope with all
situations.

2) Using delegates allows multi-cast behaviour, which often isn't
desired.

3) Using delegates requires the delegate to be set somewhere - at what
point would you do this? Consider the situation where you want a
partial method to be executed as part of a constructor...

4) Using delegates is uglier in terms of testing for null and then
executing a delegate.

5) Using delegates could have a significant performance hit for the
situations where the partial method is called a *lot*. (Consider that
it might be inlined...)

6) The compiler has all the information available at compile-time;
delegates don't make use of this, whereas partial methods do.

7) If you have a lot of partial methods, that would require a lot of
delegate variables - which would have to be per-instance in order to
access per-instance information. This could lead to a *big* memory hit
in situations where you want to provide a rich set of partial methods.


They're certainly not always appropriate, but I don't think they're as
bad as you're making them out to be.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top