Inheritance question - Controlling Order

D

Daniel Jeffrey

Hello,

I am coming from Delphi and when I have a method in the inherited class, I
call Inherited to call the base class method.

This is handy cause you can control where and when these things happen.

Can you do this in C#?


EG


public partial class BaseForm : Form
{
public bool isMainForm = false;

public BaseForm()
{
InitializeComponent();
if (isMainForm)
BaseLibrary.BaseDM = new BaseDataModule();
}
}


public partial class MainForm : BaseForm
{
public MainForm()
{
base.IsMainForm = true;

// Call the Base method NOW!!

InitializeComponent();

}
}
 
B

Ben

Hello,

I am coming from Delphi and when I have a method in the inherited class,
I call Inherited to call the base class method.

This is handy cause you can control where and when these things happen.

Can you do this in C#?

with methods -- yes, but not with the constructor.

for your example you can do something like that:

public partial class BaseForm : Form
{

public bool IsMainForm = false;

public BaseForm(bool isMainForm)
{
IsMainForm = isMainForm;

InitializeComponent();
if (isMainForm)
BaseLibrary.BaseDM = new BaseDataModule();
}
}


public partial class MainForm : BaseForm
{
public MainForm() : base (true)
{

InitializeComponent();

}
}
 
P

Peter Duniho

Daniel said:
Hello,

I am coming from Delphi and when I have a method in the inherited class,
I call Inherited to call the base class method.

This is handy cause you can control where and when these things happen.

Can you do this in C#?

Not exactly as you've shown it, no. You can call the base constructor
from the derived constructor, but only as part of the declaration of the
constructor itself. So you can't execute arbitrary code in the
derived constructor and then call the base constructor.

However, that's not to say that there's no way to accomplish what you're
doing. One alternative that should work the same:

public partial class BaseForm : Form
{
public bool isMainForm;

public BaseForm() : this(false)
{
}

public BaseForm(bool initIsMainForm)
{
isMainForm = initIsMainForm;

InitializeComponent();
if (isMainForm)
BaseLibrary.BaseDM = new BaseDataModule();
}
}


public partial class MainForm : BaseForm
{
public MainForm() : base(true)
{
InitializeComponent();
}
}

If you have more complex logic you're trying to encapsulate, the usual
approach would be to create a private initialization method which is
called by any constructor at the appropriate time. That would allow for
more complex logic than just simple calculations and initializations.

Though, now that I think about it, since you can put any expression into
the parameter for the "base" or "this" references, I suspect you could
do just about anything you wanted if you created an evaluated anonymous
method as the parameter for the "base" or "this" reference. At least,
I'm having a hard time coming up with an example of something you
_couldn't_ do that way. :)

As a really simple example of how to complicate the above, for example:

public partial class BaseForm : Form
{
public bool isMainForm;

public BaseForm() : this(false)
{
}

public BaseForm(bool initIsMainForm)
{
isMainForm = initIsMainForm;

InitializeComponent();
if (isMainForm)
BaseLibrary.BaseDM = new BaseDataModule();
}
}


public partial class MainForm : BaseForm
{
public MainForm() : base((bool delegate() { return true; })())
{
InitializeComponent();
}
}

I didn't actually compile that to confirm that the syntax is allowed,
but assuming it is, then as long as you have a base constructor that
takes a parameter and you can create an anonymous method that returns a
value of the same type, then you'd put that anonymous method there an
evaluate it immediately as the parameter value. The code in the method
would execute prior to calling the base method.

Obviously there'd be no need to do that for the specific example you
started with, but if you had something more complex, like you want to
initialize the value based on some complicated logic that isn't a
simple, single expression, you could do something like the above.

Again, that assumes the compiler accepts the syntax. I'm not sure why
it wouldn't, but I've never tried it and I might be just talking out of
my hat here. :)

Pete
 
P

Peter Duniho

Peter said:
[...]
Though, now that I think about it, since you can put any expression into
the parameter for the "base" or "this" references, I suspect you could
do just about anything you wanted if you created an evaluated anonymous
method as the parameter for the "base" or "this" reference. At least,
I'm having a hard time coming up with an example of something you
_couldn't_ do that way. :)

Okay, just for grins I played around with that suggestion. I ran into
two issues:

1) You don't have access to instance members in the constructor
declaration, so you couldn't use this technique to initialize instance
members.

2) For some reason, the compiler is not willing to evaluate a
completely anonymous method. It requires that the method be cast to
some known delegate type before being evaluated, which requires
declaring an appropriate delegate type to use for the casting, and then
of course including the casting in the syntax.

So instead of something like this:

public ClassName() : base((bool delegate { return true; })())
{
}

You wind up with something more like this:

delegate bool BoolDelegate();

public ClassName() : base(((BoolDelegate)(bool delegate { return
true; }))())
{
}

I suppose that's an okay work-around but IMHO it really starts to muck
up how the code looks. Especially given that you can't access instance
members anyway, I think I'd go with the "initialization method" solution
for dealing with situations that are too complex to handle with basic
"base" and "this" in the constructor declaration syntax.

Pete
 
J

Jon Skeet [C# MVP]

2) For some reason, the compiler is not willing to evaluate a
completely anonymous method. It requires that the method be cast to
some known delegate type before being evaluated, which requires
declaring an appropriate delegate type to use for the casting, and then
of course including the casting in the syntax.

Absolutely. An anonymous function (whether it's an anonymous method or
a lambda expression in C# 3) *must* be converted to a specific
delegate type at the point of specification. In most normal scenarios
the conversion is implicit though. I'd count this as "not a normal
scenario" :)

Jon
 
P

Peter Duniho

Jon said:
Absolutely. An anonymous function (whether it's an anonymous method or
a lambda expression in C# 3) *must* be converted to a specific
delegate type at the point of specification. In most normal scenarios
the conversion is implicit though. I'd count this as "not a normal
scenario" :)

Yup. Once I read the relevant parts in the spec and realized that an
anonymous method declaration creates an "anonymous-method-expression"
that can be used only in specific contexts, I understood my mistakes.

I was unable to figure out an in-line way to cast the thing to a
delegate type; declaring an explicit delegate type and using that works
of course, but I thought I code make the code even goofier if I could do
everything inline. :)

By the way, reading through the spec makes me wonder at whether there's
really any point in discriminating between the term "anonymous method"
and "anonymous delegate", since as near as I can tell an anonymous
method is only usable when it's cast to a delegate type. All anonymous
methods eventually become delegates, even if they are not themselves
literally delegates.

Ah well...

Pete
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
Yup. Once I read the relevant parts in the spec and realized that an
anonymous method declaration creates an "anonymous-method-expression"
that can be used only in specific contexts, I understood my mistakes.

Righto. Have you read the section on type inference, by the way? That's
a "fun" way to kill time ;)
I was unable to figure out an in-line way to cast the thing to a
delegate type; declaring an explicit delegate type and using that works
of course, but I thought I code make the code even goofier if I could do
everything inline. :)
:)

By the way, reading through the spec makes me wonder at whether there's
really any point in discriminating between the term "anonymous method"
and "anonymous delegate", since as near as I can tell an anonymous
method is only usable when it's cast to a delegate type. All anonymous
methods eventually become delegates, even if they are not themselves
literally delegates.

The only reason I discriminate is because "anonymous delegate" isn't
part of the standard C# terminology. I figure it's best for us all to
use the same terms. It's not as bad as when there are accepted meanings
for terms and then they're abused, but it's good to be consistent.

Having said that, when talking about C# 3 I tend to use "automatic
property" instead of "automatically implemented property" (even in the
book) just because it's shorter and trips off the tongue better. So
yes, I'm a hypocrit in this respect...
 

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