out Parameter And Base Class ?

D

dahuzizyd

Hi all:
I think I had a problem with using out parameter , why the instance of
'SubClass' can't convert to 'BaseClass' ? my code is :
----------------------------------------------
using System;

namespace ConsoleApplication2
{

class Class1
{
[STAThread]
static void Main(string[] args)
{
SubClass y = new SubClass() ;
Test( out y);
}

static void Test( out BaseClass y )
{
Console.WriteLine(y.ToString());
}
}
class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass");
}
}
class SubClass : BaseClass
{
public SubClass()
{
Console.WriteLine("SubClass");
}
}
}


thanks in advance
Yadong Zhao
 
N

Nicholas Paldino [.NET/C# MVP]

dahuzizyd,

The reason you get this is because y needs to be of type BaseClass. If
you derived another class from BaseClass, say, SubClass2, then the Test
method could assign the parameter y to an instance of SubClass2. Upon
return, the variable y would not be able to be assigned to, because it is of
type SubClass2, not SubClass.

Hope this helps.
 
D

dahuzizyd

Thanks for your help .
My english is so bad that I can't show my problem clearly : - (

I write this code to make the Test method can reusnable. All class which
derived from BaseClass can be a parameter for this method.But if I write
like this:

BaseClass y ;
Test( out y);

static void Test( out BaseClass y )
{
y = new SubClass();
Console.WriteLine(1);
}

this code can be compiled . But the BaseClass will mean nothing.. If I don't
use the out word,everything is good.
So I think there are some thing that I never knew with the out word.

class Class1
{
[STAThread]
static void Main(string[] args)
{
DeriveClass y ;
Test( out y);

DeriveClass s = new DeriveClass();
DeriveClass2 s1 = new DeriveClass2();
Test1(s);
Test1(s1);
}
static void Test( out BaseClass y )
{
y = new DeriveClass();
Console.WriteLine(1);
}
static void Test1 ( BaseClass y )
{
Console.WriteLine(2);
}
}
class BaseClass
{
}
class DeriveClass : BaseClass
{

}
class DeriveClass2 : BaseClass
{

}


thanks in advance
Yadong Zhao
 
J

Jon Skeet [C# MVP]

dahuzizyd said:
Thanks for your help .
My english is so bad that I can't show my problem clearly : - (

No, I think you showed your problem fine.
I write this code to make the Test method can reusnable. All class which
derived from BaseClass can be a parameter for this method.But if I write
like this:

BaseClass y ;
Test( out y);

static void Test( out BaseClass y )
{
y = new SubClass();
Console.WriteLine(1);
}

this code can be compiled . But the BaseClass will mean nothing.. If I don't
use the out word,everything is good.
Indeed.

So I think there are some thing that I never knew with the out word

It's exactly as Nick said. You can't use a variable of a different type
(even if it's a subclass) for an "out" argument. Your Test method (in
your first post) could create a new instance of BaseClass (or a
different subclass) instead of SubClass - and at that stage, when the
method compiled, the variable wouldn't have the right kind of value.

This is specified in the C# language spec as:
<quote>
When a formal parameter is an output parameter, the corresponding
argument in a method invocation must consist of the keyword out
followed by a variable-reference of the same type as the formal
parameter.
</quote>

See http://www.pobox.com/~skeet/csharp/parameters.html for more
information about parameter passing.
 
J

Joanna Carter [TeamB]

"dahuzizyd" <[email protected]> a ecrit dans le message de %[email protected]...

| Hi all:
| I think I had a problem with using out parameter , why the instance of
| 'SubClass' can't convert to 'BaseClass' ? my code is :

I think this could be a misleading message; there is definitely a problem
with the following :

| static void Test( out BaseClass y )
| {
| Console.WriteLine(y.ToString());
| }

You cannot call any methods on y until you have assigned a valid instance to
it.

The out parameter means that the reference passed in *has* to be initialised
as it is assumed to be null. The purpose of the out modifier is to allow the
same funtionality as returning a reference from a function and should be
treated as such. Its purpose is to return references from a method not to
pass references into it.

Joanna
 
J

Jon Skeet [C# MVP]

Joanna Carter said:
"dahuzizyd" <[email protected]> a ecrit dans le message de %[email protected]...

| I think I had a problem with using out parameter , why the instance of
| 'SubClass' can't convert to 'BaseClass' ? my code is :

I think this could be a misleading message; there is definitely a problem
with the following :

It's not a misleading message - it's just that there are multiple
things wrong with the code.
| static void Test( out BaseClass y )
| {
| Console.WriteLine(y.ToString());
| }

You cannot call any methods on y until you have assigned a valid instance to
it.

The out parameter means that the reference passed in *has* to be initialised
as it is assumed to be null.

No - it's not assumed to be null. It's not definitely assigned. Big
difference :) If it were assumed to be null, you wouldn't get a
compile-time error, you'd get a NullReferenceException at run-time.
The purpose of the out modifier is to allow the
same funtionality as returning a reference from a function and should be
treated as such. Its purpose is to return references from a method not to
pass references into it.

Indeed. The reason the OP is getting the error message, however, is
that the actual argument must be a variable of exactly the same type as
the output parameter.
 
D

dahuzizyd

Thanks for your answer .

I think I understand.Before I write this code . I never pay attention to
this point of the out keyword.
:-(

Now , I rewrite my code to reach my purpose for reusnable. It's looks better
than before. :)

My code is :
-----------------------------------------
class Class1
{
[STAThread]
static void Main(string[] args)
{
BaseClass y ;
Test( out y ,typeof(DeriveClass2) );
y.WriteName();
Console.ReadLine();
}
static void Test( out BaseClass y ,Type t )
{
y = BaseClass.CreateInstance(t);
}
}
class BaseClass
{
public static BaseClass CreateInstance(Type deriveClassType)
{
return (BaseClass)System.Activator.CreateInstance(deriveClassType);
}
public void WriteName()
{
Console.WriteLine(this.ToString());
}
}
class DeriveClass : BaseClass
{
}
class DeriveClass2 : BaseClass
{
}

Thanks and Regards
Yadong Zhao
 
J

Joanna Carter [TeamB]

"Jon Skeet [C# MVP]" <[email protected]> a écrit dans le message de (e-mail address removed)...

| No - it's not assumed to be null. It's not definitely assigned. Big
| difference :) If it were assumed to be null, you wouldn't get a
| compile-time error, you'd get a NullReferenceException at run-time.

You are right, it's early and my brain isn't yet communicating clearly :)

| > The purpose of the out modifier is to allow the
| > same funtionality as returning a reference from a function and should be
| > treated as such. Its purpose is to return references from a method not
to
| > pass references into it.
|
| Indeed. The reason the OP is getting the error message, however, is
| that the actual argument must be a variable of exactly the same type as
| the output parameter.

Agreed. I think the problem is that the OP does not yet understand what the
out modifier actually does.

private void TestOut(out BaseClass value)
{
value.Test();
}

This code actually raise two errors :

Error 1 Use of unassigned out parameter 'value' F:\Test\Form1.cs 31 7 Test
Error 2 The out parameter 'value' must be assigned to before control leaves
the current method F:\Test\Form1.cs 29 18 Test

So the OP's examples definitely won't compile for other reasons than the
faulty parameter type. These errors make it clear that an out parameter
*must* be assigned something and not used to pass something in.

Can I wake up now ? :)

Joanna
 
J

Jon Skeet [C# MVP]

Joanna Carter said:
| No - it's not assumed to be null. It's not definitely assigned. Big
| difference :) If it were assumed to be null, you wouldn't get a
| compile-time error, you'd get a NullReferenceException at run-time.

You are right, it's early and my brain isn't yet communicating clearly :)

No problem. I suspected you probably realised that, but thought it
would be worth clarifying it for the sake of everyone else :)
| > The purpose of the out modifier is to allow the
| > same funtionality as returning a reference from a function and should be
| > treated as such. Its purpose is to return references from a method not
to
| > pass references into it.
|
| Indeed. The reason the OP is getting the error message, however, is
| that the actual argument must be a variable of exactly the same type as
| the output parameter.

Agreed. I think the problem is that the OP does not yet understand what the
out modifier actually does.

Quite possibly. The reason you can't use an out argument of a derived
type is probably the most subtle part of it, to be honest.
private void TestOut(out BaseClass value)
{
value.Test();
}

This code actually raise two errors :

Error 1 Use of unassigned out parameter 'value' F:\Test\Form1.cs 31 7 Test
Error 2 The out parameter 'value' must be assigned to before control leaves
the current method F:\Test\Form1.cs 29 18 Test

So the OP's examples definitely won't compile for other reasons than the
faulty parameter type. These errors make it clear that an out parameter
*must* be assigned something and not used to pass something in.
Yup.

Can I wake up now ? :)

Yup - go get some coffee :)
 
D

dahuzizyd

This question is from our project . My origin code is an example for
project's code .
The project's framework design and coding is aleary finished . The desinger
and coder of the framework is at another country . So we have no chance to
change it and I think I must know the real reason for this. Thanks for your
help !

Thanks and Regards
Yadong Zhao
 
J

Jon Skeet [C# MVP]

dahuzizyd said:
Thanks for your answer .

I think I understand.Before I write this code . I never pay attention to
this point of the out keyword.
:-(

Now , I rewrite my code to reach my purpose for reusnable. It's looks better
than before. :)

Good. It's worth avoiding out parameters where you can though,
preferring to use straight return values. That's simpler, and more
obvious.
 
J

Joanna Carter [TeamB]

"dahuzizyd" <[email protected]> a ecrit dans le message de (e-mail address removed)...

| Now , I rewrite my code to reach my purpose for reusnable. It's looks
better
| than before. :)

In actual fact, what you are doing is implementing the Factory Method design
pattern.

Using an out parameter is not the usual way of doing this, at least for
returning a single instance of a given type.

You could just as well do this :

class Class1
{
[STAThread]
static void Main(string[] args)
{
BaseClass y = BaseClass.CreateInstance(typeof(DeriveClass2));
y.WriteName();
Console.ReadLine();
}
}

Or if you still feel that you need to have a Factory Method in Class1 as
well, then just use a method that returns an object of BaseClass type.

class Class1
{
static BaseClass Test(Type t )
{
return BaseClass.CreateInstance(t);
}

[STAThread]
static void Main(string[] args)
{
BaseClass y = Test(typeof(DeriveClass2));
y.WriteName();
Console.ReadLine();
}
}

Joanna
 

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