strange compile when using inheritance

T

tony

Hello!

My question is about calling this method CollectData below but I get a
compile error that I shouldn't have because the type parameter is correct.
The compile error is the following:
C:\PK\Development\Products\UTCAS\4.0\SRC\MeltPracApplication\Dialog\Composit
ionForm.cs(942): Argument '1': cannot convert from 'ref
MeltPracData.MeltPracDataComposition' to 'ref
MeltPracCommon.IDialogPostData'

public bool CollectData(ref IDialogPostData post)
{...}

This IDialogPostData is an interface of type
MeltPracCommon.IDialogPostData.
We have an abstract class called MeltPracData which has the following
definition
public abstract class MeltPracData : IDialogPostData
{...}
As you can see this MeltPracData implements IDialogPostData

I have another class called MeltPracDataComposition which has the following
definition.
public class MeltPracDataComposition : MeltPracData
{...}
As you can see this MeltPracDataComposition is an MeltPracData according to
general inheritance rules.

In my program I have these two statement
MeltPracDataComposition mpd = new MeltPracDataComposition();
CollectData(ref mpd);
which cause compile error.
In my opinion these two statements shouldn't cause any compile error.

Some comment why these two statements shouldn't cause any compile error.
First of all I instansiate an MeltPracDataComposition which is an
MeltPracData
and a MeltPracData implement IDialogPostData.
This mean that I can send an actual parameter of type
MeltPracDataComposition
and receive it as an formal parameter of type IDialogPostData.

Another strange thing is if a remove the ref in the CollectData and
call it in this way CollectData(mpd);
I don't get any compile error.

I know what ref means but I can't figure out why I get a compile error when
having this ref in the method definition for collectData.

//Tony
 
M

Marc Gravell

Since the "post" param to "CollectData" is ref, so "CollectData" can
update it. And "CollectData" is free to assign anything that is an
IDialogPostData. Such as "MyOtherClass : IDialogPostData". This means
that the compiler cannot verify the integrity of your "mpd" variable.

In most cases, "ref" is used incorrectly for parameters; do you
*really* need to re-assign the variable within the method? Or is this
intended to support reference-semantics for structs that support this
interface?

Anyway, you can probably fix it (keeping the ref) by:
IDialogPostData iparam = mpd;
CollectData(iparam);
mpd = (MeltPracDataComposition) iparam;

The easier fix is to remove the "ref".

Marc
 
T

tony

Hello!!

I don't understand you.
I mean because MeltPracDataComposition is an IDialogPostData it should work.

Can you explain in another way perhaps.

//Tony
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Why are you using ref in the first place?

The compiler is correct , the reason is a little difficult to explain
though.

Let's say that you have
interface I{}
class A:I{}
class B:I{}

both A & B implement I but they have no relationship between them.

You can have:
method ( I i ){

i = new B();
i = new A();
}

it does not matter if I originally had an instance of A or B

but when you have:
method ( ref I i ){

i = new B();
}

and you call it like
method( new A() );

you would end up with i that contained originally a reference to A being
assigned to a reference to B

This is clearly an error and that's why the compiler complains
 
J

Jon Skeet [C# MVP]

tony said:
I don't understand you.
I mean because MeltPracDataComposition is an IDialogPostData it should work.

No, it shouldn't. "ref" parameters need to be *exactly* the right type.

Consider the following code:

public void MakeAnObject (ref object foo)
{
foo = new object();
}

string x = "hello";
MakeAnObject (ref x);

This is illegal, because it ends up with the variable x being a
reference to an object, not a string.

See http://www.jaggersoft.com/csharp_standard/14.4.2.1.htm

<quote>
A function member is said to be an applicable function member with
respect to an argument list A when all of the following are true:

* 2 The number of arguments in A is identical to the number of
parameters in the function member declaration.
* 3 For each argument in A, the parameter passing mode of the
argument (i.e., value, ref, or out) is identical to the parameter
passing mode of the corresponding parameter, and
o 4 for a value parameter or a parameter array, an implicit
conversion (§13.1) exists from the type of the argument to the type of
the corresponding parameter, or
o 5 for a ref or out parameter, the type of the argument is
identical to the type of the corresponding parameter.
</quote>

The last sentence is the important bit.

Jon
 

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