473,788 Members | 2,706 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Strange asymmetric polymorphism when using out parameters. Bug?

Introduction:
As we all know, values of any class may be assigned to a reference of a
superclass.
This is simple polymorphism.
So if you have a class A and a class B that inherits from A you can write a
method that returns an instance of B and assign that to a reference of type
A. (Trivial)
Problem:
If you rewrite the method so that it no longer returns an instance of B as a
return value but as an out parameter we are in trouble!
The polymorphic rules that applied in the first case don't apply now for
some strange reason.
We get a compile error if we try to call the method with a reference of type
A.
Questions:
Is this a bug or is there a technical reason for this?
Perhaps it would be harder to resolve overloaded methods if you could do as
I want?
It seems to me like an out parameter actually is behaving more like a ref
parameter under the covers.
Example code below:
/Regards
Mårten Herberthson

class A{} //Class A
class B : A{} //Class B inherits from A (why am I telling you this ;-)

class Class1
{
//A method that returns an instance of a B as a return value
static B GetBAsReturnVal ue() {return new B();}
//A method that returns an instance of a B as an out parameter
static void GetBAsOutParame ter(out B outB) {outB = new B();}

[STAThread]
static void Main(string[] args)
{
//The trivial case using a reference of type B
B b;
b = GetBAsReturnVal ue(); //works fine
GetBAsOutParame ter(out b); //works fine

//The case that should be equally trivial but isn't.
//We use a variable of type A instead of B.
//This should be no problem since any reference to an A
//may be assigned values of type B
A a;
a = GetBAsReturnVal ue(); //works fine as expected.
GetBAsOutParame ter(out a); //DOES NOT COMPILE!!!
}
}
Nov 15 '05 #1
6 2556
Marten,

While you are right in your comments about polymorphism, your assumption
that the two cases of returning a value through a parameter and the actual
return value are logically the same is incorrect.

The difference is that the routine can access the value passed into the
out parameter, while initially, there is no value in the return value (so to
speak).

So, they are different.

Basically, you are doing an end-run around type safety if you allow A to
be passed for B. The reason for this is that what if there is a class C
which extends A and in the method it assigns an instance of C to the output
parameter. Yes, it could be cast down to A, but what is the point of the
parameter being declared as B at that point? Type-safety goes out the
window. I wouldn't use a language that explicily ignored these things.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- ni************* *@exisconsultin g.com

"Mårten Herberthson" <he*********@ho tmail.com> wrote in message
news:u5******** ******@TK2MSFTN GP11.phx.gbl...
Hi Selvin,

Thank you for your reply.

Obviously I could change the formal parameter to be of type A just to make
it compile, but my question is on a more fundamental level.
According to the rules of polymorphism it should be possible to do what I
want. Remember, when I return a B as a return value I can retrieve it in to an A so I should be able to do the same thing when *returning* it as an out parameter.

It is true what you write that "you could not cast (B)a 'cause A isn't
delvered from B", but since I am *returning* a B (out) there is no need to
cast the variable "a" to a B as it would have been if the parameter was ref. Again: It works then using a return value; it should work when using an out parameter. The two cases are logically the same.

/Regards

Mårten

"Selvin" <no***********@ osadkowski.com. pl_nospam> wrote in message
news:bg******** **@atlantis.new s.tpi.pl...
class A{} //Class A
class B : A{} //Class B inherits from A (why am I telling you this ;-)
class Class1
{
//A method that returns an instance of a B as a return value
static B GetBAsReturnVal ue() {return new B();}
//A method that returns an instance of a B as an out parameter
static void GetBAsOutParame ter(out B outB) {outB = new B();}


try
static void GetBAsOutParame ter(out A outB) {outB = new B();}

[STAThread]
static void Main(string[] args)
{
//The trivial case using a reference of type B
B b;
b = GetBAsReturnVal ue(); //works fine
GetBAsOutParame ter(out b); //works fine

//The case that should be equally trivial but isn't.
//We use a variable of type A instead of B.
//This should be no problem since any reference to an A
//may be assigned values of type B
A a;
a = GetBAsReturnVal ue(); //works fine as expected.
GetBAsOutParame ter(out a); //DOES NOT COMPILE!!!
}


you could not cast (B)a 'cause A isn't delvered from B
}


--
Selvin - Przemek Sulikowski
se****@osadkows ki.com.pl


Nov 15 '05 #2
Mårten,

<snip>
The polymorphic rules that applied in the first case don't apply now for
some strange reason. The "polymorphi c rules" don't apply because the situation is different.
According "Liskovs Substitutable Principle" you can use B instead of A, but
the opposite is not true. You can't use A instead of B and this is exactly
what happening with GetBAsOutParame ter(out a); //DOES NOT COMPILE!!!

Compiler dosen't have any idea how to convert (cast) A to B.

Of course you could provide this information to the compiler, but the bigger
question emerges then in what circumstances should you do so? (Can you
provide an example when such twist is needed?)
Ron
Nov 15 '05 #3
Ron Bullman <ro********@mai l.com> wrote:
GetBAsOutParame ter(out a); //DOES NOT COMPILE!!!

Compiler dosen't have any idea how to convert (cast) A to B.


In a single-threaded world, it wouldn't need to. The initial value (if
any) in an out parameter can never be used by the called method. The
problem is that in a multi-threaded world, the called method can assign
an initial value and *then* read from the parameter, which may have its
value changed by another thread to a different value which is
compatible with the original variable but not the narrower one in the
called method.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too
Nov 15 '05 #4
Hi Jon

Thank you both for understanding my problem and for your answer.

I have talked to allot of people about this including Anders Hejlsberg when
I met him at the PDC. Anders gave me an answer but since both of us had been
drinking red wine it was a bit confusing.

Your answer is the first one that I understand.

Thank you,

Mårten

"Jon Skeet" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@news.microsof t.com...
Mårten Herberthson <he*********@ho tmail.com> wrote:

<snip>
It seems to me like an out parameter actually is behaving more like a ref parameter under the covers.


Yes, an out parameter is *exactly* like a ref parameter under the
covers, with the only difference being that of definite assignment. (An
out parameter doesn't need to be definitely assigned before being used
in the calling method, and must be definitely assigned before the
method returns normally, at which point it is definitely assigned in
the calling method.)

There is, however, one reason why you shouldn't be able to use "out" in
the way you're considering. Bear in mind that the variable shares the
same slot as the original variable - and that another thread may be
able to change the value of that slot while the method is executing.
Consider the following code:

using System;
using System.Threadin g;

public class Test
{
static object o;

static void Main()
{
new Thread (new ThreadStart (Bar)).Start();
Foo (out o);
}

static void Foo (out string x)
{
x = "hello";
Thread.Sleep (5000);
Console.WriteLi ne (x.Length);
}

static void Bar ()
{
Thread.Sleep(20 00);
o = new object();
}
}

(I haven't put any memory barriers in, but it would be easy to do so.)

The code for Foo assumes that the value of x will always be a reference
to a string or null - but by the time it tries to write x.Length, the
value of o will actually be a reference to a plain object.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too

Nov 15 '05 #5
Mårten Herberthson <he*********@ho tmail.com> wrote:
I have talked to allot of people about this including Anders Hejlsberg when
I met him at the PDC. Anders gave me an answer but since both of us had been
drinking red wine it was a bit confusing.


LOL :)

I'd be interested to see the spec of a language designed *only* during
the periods where the authors were very, very drunk. No doubt it would
be terrible in itself, but I'm sure there'd be some great ideas in
there too - not because no-one could think of them when sober, but
because they might be quickly dismissed as being implausible or even
impossible when sober.

Glad my answer makes sense though.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too
Nov 15 '05 #6
Jon,

OK, I had wrong understanding how out works. I tought if initialized then it
could be used by the called method, but indeed "The initial value (if any)
in an out parameter can never be used by the called method".
Ron
"Jon Skeet" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@news.microsof t.com...
Ron Bullman <ro********@mai l.com> wrote:
GetBAsOutParame ter(out a); //DOES NOT COMPILE!!!

Compiler dosen't have any idea how to convert (cast) A to B.


In a single-threaded world, it wouldn't need to. The initial value (if
any) in an out parameter can never be used by the called method. The
problem is that in a multi-threaded world, the called method can assign
an initial value and *then* read from the parameter, which may have its
value changed by another thread to a different value which is
compatible with the original variable but not the narrower one in the
called method.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too

Nov 15 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
4548
by: rashkatsa | last post by:
Hi all ! I have written a little module called 'polymorph' that allows to call different methods of a class that have the same name but that have not the same number of arguments. *args are supported. You could find the module attached to this message. As in python, you could not define two method with same name (the second one override the first one), i have choosen to design it through private prefix '__' (defined method names and...
4
2404
by: Leslaw Bieniasz | last post by:
Cracow, 20.09.2004 Hello, I need to implement a library containing a hierarchy of classes together with some binary operations on objects. To fix attention, let me assume that it is a hierarchy of algebraic matrices with the addition operation. Thus, I want to have a virtual base class class Matr;
4
4431
by: Leslaw Bieniasz | last post by:
Cracow, 20.10.2004 Hello, As far as I understand, the generic programming basically consists in using templates for achieving a static polymorphism of the various code fragments, and their reuse for various template parameters. I wonder if there exist techniques for achieving a dynamic polymorphism using the generic programming. Is this possible? If yes, can anyone show me simple examples in C++
7
1370
by: deancoo | last post by:
I'm having some trouble with a couple of classes I've created (base and derived). I had defined a function in a derived class, and then overloaded that function name in a class derived from the first derived class. Now I need to store objects instantiated from these classes (excluding the base class) in a container. The container is defined to hold objects of the base class type. So far so good, however, when it comes time to use the...
13
2001
by: Andy Chau | last post by:
I try to use RSA to implement the following scheme but wasn't sucessful. Sever encrypt a message using a public key, the client decrpyt the message using a private key. I don't want the client to be able to encrypt a message. However, using the Crypto API I need to pass in both the private and public key pairs in order to decrypt the message. When the client has both private and public key, it can just use the public
9
1659
by: Karahan Celikel | last post by:
Here are three simple classes: class A { public void DoIt(B b) { DoSomething(b); } public void DoSomething(B b) {
11
2978
by: chsalvia | last post by:
I've been programming in C++ for a little over 2 years, and I still find myself wondering when I should use polymorphism. Some people claim that polymorphism is such an integral part of C++, that anybody who doesn't use it might as well just program in plain C. I totally disagree with this, because I think C++ has a lot of great features apart from polymorphism, such as the ability to organize code into classes, code reuse through...
3
4649
by: Bruce | last post by:
How can I encrypt strings using an asymmetric key? I want to encrypt short strings (credit card numbers, etc.) and save the encrypted strings into a database. When accessing the data (i.e. the web admin), he will provide a password (the decryption key). There are DLL components (http://www.aspencrypt.com), but I can't register a DLL on the machine (hosted server). If you know of something, or some code samples, it'll be highly...
17
3883
by: Bart Friederichs | last post by:
Hello, I created the following inheritance: class Parent { public: void foo(int i); }; class Child : public Parent {
0
9656
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9498
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10177
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10113
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9969
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
5402
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4074
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3677
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2896
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.