473,320 Members | 1,990 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

C# inheritance broken?

C# is an impressive language...but it seems to have one big limitation
that, from a C++ background, seems unacceptable.

Here's the problem:

I have a third-party Document class. (This means I can't change the
Document class.) I want to extend this (inherit from Document) as
MyDocument, adding new events and application-specific methods and
properties.

I submit that this can't be done in C#.

Consider this example:

class MyDocument : public Document

This doesn't work because the only way to open an existing Document is
using the static method Document.Load(string FileName), which returns a
Document object. There doesn't seem to be any way to convert or cast a
Document object to a MyDocument object. There is therefore no way to
"Load" a MyDocument object!
>From reading LOTS of posts on this group, the standard answers are:
1. "Wrap" the object, as follows:
class MyDocument
{
protected Document TheDocument;
}

But...this means that I have to wrap EACH of the hundreds of methods
and properties needed to manipulate the Document object. This is
clearly a case for inheritance, to allow the base class properties and
methods to be automatically available, with enhancements from the
derived class.

2. In MyDocument.Load, call Document.Load, and then COPY all of
Document's members to MyDocument.

BUT, this is prohibitive because COPYING all of Document's members is
prohibitive in terms of run time, and also in terms of development
effort (lines of code, and therefore, potential bugs).

In C++, I would do something like this:

class MyDocument : public Document
{
public static MyDocument Load(string FileName)
{
return (MyDocument)Document.Load(FileName);
}
}

So my conclusion is that C# inheritance is broken (in practice) because
of its strict type-checking, and no allowance for such a common
scenario.

Did I miss something?

Jan 26 '07
64 3379

<gr****@isaacsoft.comwrote in message
news:11**********************@a34g2000cwb.googlegr oups.com...
Jake Stevenson's posted an example earlier on this thread.

That's all fine, but it does not get around the cost of *copying* the
object.

I suppose that what I really want here is a sort of "reference"
constructor, something like the "Attach" method in ATL's CComPtr
class. Come to think of it, CComPtr actually "wraps" the interface
being used, but its wrapper is generated automatically by a
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!
What bastard variant of C++ has an "#import" directive?
Jan 30 '07 #51
That would be Microsoft Visual C++, all versions since at least 6.0.

On Jan 30, 11:40 am, "Mike Schilling" <a...@newsgroup.nospamwrote:
<gro...@isaacsoft.comwrote in messagenews:11**********************@a34g2000cwb.g ooglegroups.com...
Jake Stevenson's posted an example earlier on this thread.
That's all fine, but it does not get around the cost of *copying* the
object.
I suppose that what I really want here is a sort of "reference"
constructor, something like the "Attach" method in ATL's CComPtr
class. Come to think of it, CComPtr actually "wraps" the interface
being used, but its wrapper is generated automatically by a
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!What bastard variant of C++ has an "#import" directive?
Jan 30 '07 #52
Usage of #import:

#import <filename.ocx>

Just typing this line in Visual Studio will generate a .h and a .cpp
file wrapping all of the methods and properties of an OCX control.

On Jan 30, 11:40 am, "Mike Schilling" <a...@newsgroup.nospamwrote:
<gro...@isaacsoft.comwrote in messagenews:11**********************@a34g2000cwb.g ooglegroups.com...
Jake Stevenson's posted an example earlier on this thread.
That's all fine, but it does not get around the cost of *copying* the
object.
I suppose that what I really want here is a sort of "reference"
constructor, something like the "Attach" method in ATL's CComPtr
class. Come to think of it, CComPtr actually "wraps" the interface
being used, but its wrapper is generated automatically by a
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!What bastard variant of C++ has an "#import" directive?
Jan 30 '07 #53
Mike Schilling wrote:
<gr****@isaacsoft.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
[...]
But you haven't shown a C++ solution either, since the cast in your example
doesn't work.
If a constructor is added like in the following example, it will work.
Think that was the intention of Tony.

class Document
{
public:
Document(){}
static Document Load() { return Document(); }
};

class MyDocument : public Document
{
public:
MyDocument() {}
MyDocument(Document& s) : Document(s) {}
static MyDocument Load() { return Document::Load(); }
};

int main(int argc, char* argv[])
{
MyDocument s = MyDocument::Load();
return 0;
}

Andre

Jan 30 '07 #54
gr****@isaacsoft.com wrote:
Jake Stevenson's posted an example earlier on this thread.

[...]

preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!
It should have one, since it will generate a Interop DLL if you add a
COM dll reference. But why don't you automatically write and let a small
program do you this for you via reflection ? Should be fairly simple to
generate a MyDocument class with all the methods of Document
implemented, which all are delegating the call to an internal Document
object ?

By the way a object holding more than 100 methods, is IMHO somewhat
overloaded with methods - but that's another story.

Andre
Jan 30 '07 #55
Andre,

That's great for C++. But in C# you can't set "base" in a
constructor.

Tony

On Jan 30, 2:48 pm, Andre Kaufmann <andre.kaufmann_re_mo...@t-
online.dewrote:
Mike Schilling wrote:
<gro...@isaacsoft.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
[...]
But you haven't shown a C++ solution either, since the cast in your example
doesn't work.

If a constructor is added like in the following example, it will work.
Think that was the intention of Tony.

class Document
{
public:
Document(){}
static Document Load() { return Document(); }

};

class MyDocument : public Document
{
public:
MyDocument() {}
MyDocument(Document& s) : Document(s) {}
static MyDocument Load() { return Document::Load(); }

};

int main(int argc, char* argv[])
{
MyDocument s = MyDocument::Load();
return 0;

}

Andre

Jan 30 '07 #56
Reflection is no good, because of the amount of time it takes to make
a copy for a large document.

BTW, you'll find lots of properties and methods, buried many layers
deep, in IWebBrowser and IHtmlDocument also.

Tony

On Jan 30, 2:57 pm, Andre Kaufmann <andre.kaufmann_re_mo...@t-
online.dewrote:
gro...@isaacsoft.com wrote:
Jake Stevenson's posted an example earlier on this thread.
[...]
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!

It should have one, since it will generate a Interop DLL if you add a
COM dll reference. But why don't you automatically write and let a small
program do you this for you via reflection ? Should be fairly simple to
generate a MyDocument class with all the methods of Document
implemented, which all are delegating the call to an internal Document
object ?

By the way a object holding more than 100 methods, is IMHO somewhat
overloaded with methods - but that's another story.

Andre

Jan 30 '07 #57
Hi,

<gr****@isaacsoft.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
|No, it's simply bad design of the base class, or trying to made a bad use
of
| the class.
|
| You say the base class is designed poorly. So what would a GOOD
| design look like? The constraints are:
| - Original 'Document' object has been serialized as a 'Document.'
| - Reflection (to make a copy) is impractical because it is time-
| intensive.
| - Wrapping (MyDocument "contains" a Document" is impractical because
| of the large numbers of methods that would have to be reproduced.

What about:

class D{

public D( string file ) { LoadDoc(file); }
protected virtual void LoadDoc( string file ) {}
}

class D1:D
{
public D1( string file ):base(file){}
protected override void LoadDoc( string file )
{
base.LoadDoc();
// my stuff
}

public static D1 GetD1( string file ){ return new D1( file ); }

}

You then can do D1.GetD1( file) and get a D1
--
Ignacio Machin
machin AT laceupsolutions com
Jan 30 '07 #58
Ignacio,

That would work great, except that serialization (used by LoadDoc to
read the document from a file) does not load a new object into "this"
or "base". It always creates a new object of whatever type was
originally serialized, in this case, a Document object. This new
Document object cannot be cast to a MyDocument, nor can it be assigned
to "this" or "base", because these are always read-only.

Tony

On Jan 30, 4:55 pm, "Ignacio Machin \( .NET/ C# MVP \)" <machin TA
laceupsolutions.comwrote:
Hi,

<gro...@isaacsoft.comwrote in message

news:11**********************@l53g2000cwa.googlegr oups.com...
|No, it's simply bad design of the base class, or trying to made a bad use
of
| the class.
|
| You say the base class is designed poorly. So what would a GOOD
| design look like? The constraints are:
| - Original 'Document' object has been serialized as a 'Document.'
| - Reflection (to make a copy) is impractical because it is time-
| intensive.
| - Wrapping (MyDocument "contains" a Document" is impractical because
| of the large numbers of methods that would have to be reproduced.

What about:

class D{

public D( string file ) { LoadDoc(file); }
protected virtual void LoadDoc( string file ) {}

}

class D1:D
{
public D1( string file ):base(file){}
protected override void LoadDoc( string file )
{
base.LoadDoc();
// my stuff

}

public static D1 GetD1( string file ){ return new D1( file ); }

}

You then can do D1.GetD1( file) and get a D1

--
Ignacio Machin
machin AT laceupsolutions com

Jan 31 '07 #59
gr****@isaacsoft.com wrote:
Andre,

That's great for C++. But in C# you can't set "base" in a
constructor.
Was only a valid sample of how to do it in C++. In C# surely you can't
do this.

Andre
Jan 31 '07 #60
gr****@isaacsoft.com wrote:
Reflection is no good, because of the amount of time it takes to make
a copy for a large document.
It wasn't my intention to use reflection directly, but to use it to
create new source code, which has implemented all methods of the
Document object, so that you don't have to do the wrapping by "hand".

Andre
Jan 31 '07 #61
http://www.codeproject.com/csharp/WrapiAddin.asp
"Andre Kaufmann" <an*********************@t-online.dewrote in message
news:eq**************@TK2MSFTNGP03.phx.gbl...
gr****@isaacsoft.com wrote:
>Reflection is no good, because of the amount of time it takes to make a
copy for a large document.

It wasn't my intention to use reflection directly, but to use it to create
new source code, which has implemented all methods of the Document object,
so that you don't have to do the wrapping by "hand".

Andre


Jan 31 '07 #62
On Jan 30, 12:48 pm, Andre Kaufmann <andre.kaufmann_re_mo...@t-
online.dewrote:
Mike Schilling wrote:
<gro...@isaacsoft.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
[...]
But you haven't shown a C++ solution either, since the cast in your example
doesn't work.

If a constructor is added like in the following example, it will work.
Think that was the intention of Tony.

class Document
{
public:
Document(){}
static Document Load() { return Document(); }

};

class MyDocument : public Document
{
public:
MyDocument() {}
MyDocument(Document& s) : Document(s) {}
static MyDocument Load() { return Document::Load(); }

};

int main(int argc, char* argv[])
{
MyDocument s = MyDocument::Load();
return 0;

}
Aren't you forgetting something? Where is the copy constructor for
Document that accepts a pointer to a Document and creates a new
document from it? (Invoked on the line:

MyDocument(Document& s) : Document(s) {}

) Or is this copy constructor somehow automatically generated by the C
++ compiler?

Jan 31 '07 #63
Bruce Wood wrote:
[...]
MyDocument(Document& s) : Document(s) {}

) Or is this copy constructor somehow automatically generated by the C
++ compiler?

Exactly. C++ will automatically generate a copy constructor on a binary
basis (memcopy) or will call a user defined one for each of the class
variables. However, a developer can make the copy constructor private in
a class and then you surely can't construct an object as I did in the
example.

Andre

Feb 1 '07 #64
Hi,

"Jake Stevenson" <ja***********@gmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
>
Something similar can be implemented in the base class and would be
inherited by your class. There may be a performance issue with
Reflection though.
In C++ I remember this idea has a name, a copycon constrctor?

What strike me as weird is what is the problem in handling a Docment in the
first place, IMO MyDocument extend Document but the application should be
made to handle Document as default. And finally the readed file IS A
document.

Feb 4 '07 #65

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

Similar topics

37
by: Mike Meng | last post by:
hi all, I'm a newbie Python programmer with a C++ brain inside. I have a lightweight framework in which I design a base class and expect user to extend. In other part of the framework, I heavily...
5
by: Robert Spoons | last post by:
Can you look over this code, preferably try it, and comment? I believe the 'extend' function below will allow you to use full 'class inheritance' in javascript, but I would like to verify it. ...
19
by: qazmlp | last post by:
class base { // other members public: virtual ~base() { } virtual void virtualMethod1()=0 ; virtual void virtualMethod2()=0 ; virtual void virtualMethod3()=0 ;
14
by: Steve Jorgensen | last post by:
Recently, I tried and did a poor job explaining an idea I've had for handling a particular case of implementation inheritance that would be easy and obvious in a fully OOP language, but is not at...
2
by: Andrew Ducker | last post by:
I'm implementing a singleton using the example at: http://www.yoda.arachsys.com/csharp/singleton.html as a basis (second example). However - I have about 20 classes I wish to make singletons -...
6
by: Pascal Polleunus | last post by:
Hi, I'm wondering if there could be problems related to inheritance in the following scenario (with PostgreSQL 7.4.1)... 1 A-table, abstract. Max 10 B-tables that inherit from A, with...
31
by: John W. Kennedy | last post by:
I quite understand about prototypes and not having classes as such, but I happen to have a problem involving blatant is-a relationships, such that inheritance is the bloody obvious way to go. I can...
2
by: groups | last post by:
C# is an impressive language...but it seems to have one big limitation that, from a C++ background, seems unacceptable. Here's the problem: I have a third-party Document class. (This means I...
23
by: Dave Rahardja | last post by:
Since C++ is missing the "interface" concept present in Java, I've been using the following pattern to simulate its behavior: class Interface0 { public: virtual void fn0() = 0; };
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.