Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / March 2006

Tip: Looking for answers? Try searching our database.

Copy constructor?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Axel Dahmen - 22 Feb 2006 21:05 GMT
Hi,

I have created a class adding some Functionality to a generic class and
derived it from that:

 class MyTypedClass : MyGenericClass
 {}

Within a class library project, all functions work with the generic version,
but in my Web Application project I'm dealing with the derived version
(basically adding type to the generic version). But the following doesn't
seem to be possible:

 MyTypedClass mtc = (MyTypedClass)(new MyGenericClass());

Is it possible to create kind of a copy constructor in C#, like

 class MyTypedClass : MyGenericClass
 {
   public MyTypedClass(MyGenericClass mgc) : base(mgc)   {}
 }

TIA,
Axel Dahmen
Daniel O'Connell [C# MVP] - 23 Feb 2006 05:11 GMT
> Hi,
>
[quoted text clipped - 18 lines]
>    public MyTypedClass(MyGenericClass mgc) : base(mgc)   {}
>  }

No, the language doesn't support copy constructors. You'd have to do
MyTypedClass mtc = new MyTypedClass(new MyGenericClass());
Axel Dahmen - 23 Feb 2006 09:25 GMT
Thanks for trying to help...

> > Is it possible to create kind of a copy constructor in C#, like
> >
[quoted text clipped - 5 lines]
> No, the language doesn't support copy constructors. You'd have to do
> MyTypedClass mtc = new MyTypedClass(new MyGenericClass());

Sorry, I didn't get that. What is the difference between your line and my
given prototype?  What should the constructor prototype look like to make
up-casts possible?

IMHO, if the derived class doesn't introduce new fields, then up-casting
should not throw an InvalidCastException.

Why can typed DataSets up-cast DataRows to typed DataRows and why do I get a
runtime exception if I do the same?

 public UsersRow NewUsersRow() {
   return ((UsersRow)(this.NewRow()));
 }

Your help is quite appreciated!

Tnx,
Axel Dahmen
Nick Hounsome - 23 Feb 2006 12:33 GMT
What are you really trying to do?

MyTypedClass mtc = (MyTypedClass)(new MyGenericClass());  // ????????

What is wrong with:

MyTypedClass mtc = new MyTypedClass();

If you want a copy of an existing object then implement ICloneable in both
base and derived  (+ a typesafe overload)

class MyTypedClass : MyGenericClass, ICloneable
{
   public object ICloneable.Clone()
   {
       return Clone();
   }

   public MyTypedClass Clone()
   {
       return aCopy;
   }
}

MyGenericClass mtc1 = new MyTypedClass();

MyTypedClass mtc1 = mtc1.Clone();  // doesn't require knowledge of
MyTypeClass here

>> Hi,
>>
[quoted text clipped - 21 lines]
> No, the language doesn't support copy constructors. You'd have to do
> MyTypedClass mtc = new MyTypedClass(new MyGenericClass());
Axel Dahmen - 23 Feb 2006 13:42 GMT
Hi Nick,

problem is that I only have a base class object which I need to *cast* to a
derived object. So, basically, my situation is something like this:

  MyBaseClass mbc = new MyBaseClass(..., ..., ..., ...);
  MyTypedClass mtc = (MyTypedClass)mbc;    // throws InvalidCastException

Disturbing part: MyTypedClass doesn't add any fields, so the cast ist
perfectly safe.

When I have VS2003 create a typed DataSet using an xsd, it does the same,
but there it works:

 public class UsersRow : DataRow
 {
   ...

   public UsersRow NewUsersRow()
   {
     return ((UsersRow)(this.NewRow()));    // NewRow() returns a DataRow;
   }

   ...
 }

Disturbing part II: UsersRow in fact *adds* new fields to DataRow. Why does
it work?

To get more into detail, cloning would yield a huge overhead. MyBaseClass is
a tree object having a collection of MyBaseClass children. I don't create it
using a constructor, instead I use a static factory function to create a
whole tree of objects and return only the root:

  MyBaseClass mbc = MyBaseClass.CreateHierarchy(..., ..., ..., ...);
  MyTypedClass mtc = (MyTypedClass)mbc;    // throws InvalidCastException

MyBaseClass is based in a separate Common project, therefore it is untyped,
i.e. only provides properties through a [] operator (in fact it forwards the
operator to a private DataRow member).

In my object I now want to provide typed access to each of the properties,
like

 string Street    {    get    {return base["Street"];}}

That's why I need the cast. It's basically the same methodology like with
MS' typed DataSets.

Any quick help is highly appreciated!!!

TIA,
Axel Dahmen

---------------------------

> What are you really trying to do?
>
[quoted text clipped - 50 lines]
> > No, the language doesn't support copy constructors. You'd have to do
> > MyTypedClass mtc = new MyTypedClass(new MyGenericClass());
Nick Hounsome - 23 Feb 2006 16:41 GMT
> Hi Nick,
>
[quoted text clipped - 26 lines]
> does
> it work?

If you look at the generated code it overrides a protected virtual method
called NewRowFromBuilder which creates a new row of the correct type. The
inference is that although NewRow is not itself virtual it calls
NewRowFromBuilder which is. No magic. No copy constructors. No explicit cast
methods.

i.e. it isn't casting it is plain old virtual method calls.

It is typical MS bad form to use magic implementation specific stuff for
this (DataRowBuilder).

> To get more into detail, cloning would yield a huge overhead.

I don't understand. Either you want a copy or you don't  - If you do then
Clone() is what you need. If you don't then just make a virtual method
called CloneSchema() or something which doesn't copy the data.

> MyBaseClass is
> a tree object having a collection of MyBaseClass children. I don't create
[quoted text clipped - 4 lines]
>   MyBaseClass mbc = MyBaseClass.CreateHierarchy(..., ..., ..., ...);
>   MyTypedClass mtc = (MyTypedClass)mbc;    // throws InvalidCastException

This can never work the way DataSet.NewRow() does.
DataSet can do magic through virtual methods because it is an instance
method.

You are using a static method so the only way you could manage it is using
types and reflection by passing typeof(MyBaseClass) as a parameter.

> MyBaseClass is based in a separate Common project, therefore it is
> untyped,
[quoted text clipped - 14 lines]
> TIA,
> Axel Dahmen
Axel Dahmen - 23 Feb 2006 18:05 GMT
> It is typical MS bad form to use magic implementation specific stuff for
> this (DataRowBuilder).

That's what I call unfair... Leaving us software developers out with an
incomplete solution, but using backdoors themselves...

> > To get more into detail, cloning would yield a huge overhead.
>
> I don't understand. Either you want a copy or you don't  - If you do then
> Clone() is what you need. If you don't then just make a virtual method
> called CloneSchema() or something which doesn't copy the data.

I must admit that I don't understand your solution. These are the concerns I
have: If Clone() yields an Object, I still have to cast that object to
MyTypedClass. But won't this cast throw InvalidCastException like a direct
cast would? And if not, would the following be valid:

 MyTypedClass mtc = (MyTypedClass)(object)mbc

Thanks for enlightening me!

BTW: I can't use the explicit operator as it yields a compiler error:
"Compiler Error CS0553: user defined conversion to/from base class".

Thanks for all your efforts!
Axel
Axel Dahmen - 23 Feb 2006 19:24 GMT
IT FINALLY WORKS !!!

:)))))

I'm using Reflection now and it's working smoothly so far... Just got to add
having different types on each child level.

This code is doing the magic in UserBase.CreateUserHierarchy  (in the new
version I'm providing the destination type as a parameter):

 UserBase curUB;
 ConstructorInfo constr;

 constr=type.GetConstructor(new Type[]{typeof(DataSet),typeof(DataSet)
          ,typeof(Type),typeof(DataRow),typeof(DataColumn)
          ,typeof(UserBase),typeof(int)});

 curUB=(UserBase)constr.Invoke(new object[]{userTblSet,roleTblSet
           ,type,row,pkCol,parent,tabOffset});

This cost me another 10 years of my life today... Thanks to all for helping
me..

Axel

----------------------------
> > It is typical MS bad form to use magic implementation specific stuff for
> > this (DataRowBuilder).
[quoted text clipped - 22 lines]
> Thanks for all your efforts!
> Axel
Nick Hounsome - 24 Feb 2006 08:17 GMT
>> It is typical MS bad form to use magic implementation specific stuff for
>> this (DataRowBuilder).
[quoted text clipped - 13 lines]
> MyTypedClass. But won't this cast throw InvalidCastException like a direct
> cast would? And if not, would the following be valid:

Your problem is that for some reason you seem think that the cast is
actually changing the object. It isn't. In all the virtual method solutions
the object really IS a MyTypedClass (because it is created as such by the
overloaded method) it is just initially known as an instance of its base
class. It is not casting in the same sense as casting an int to a float say
which actually changes something.

object Clone()
{
   return new MyTypedClass(.....);
}

The object returned is NOT a cut down, transformed or sliced MyTypedClass it
IS a MyTypedClass (as can be proved if you call GetType()) so casting it
back to MyTypedClass just involves checking to see that it really is one.

>  MyTypedClass mtc = (MyTypedClass)(object)mbc

Only works if mbc realy is a MyTypedClass (the cast to object is useless).

> Thanks for enlightening me!
>
> BTW: I can't use the explicit operator as it yields a compiler error:
> "Compiler Error CS0553: user defined conversion to/from base class".

Of course - I should have thought of that.

> Thanks for all your efforts!
> Axel

Please persist with the virtual method solution if possible as it is much
preferable to reflection for a number of reasons.
Axel Dahmen - 24 Feb 2006 10:01 GMT
> Please persist with the virtual method solution if possible as it is much
> preferable to reflection for a number of reasons.

I can't as some of the properties are readonly for a good reason. So I can
only create objects from within the constructor. Another one is that
CreateObjectHierarchy() is static, thus virtual calls of this function are
not possible.

I know Reflection (=late binding) is only a hack. Upcasting would be the
right solution here. I'm normally working with virtual functions wherever
feasible. But it is not feasible in this case. Upcasting would, also for a
number of other scenarios where you just want to add additional
functionality to given objects for example. A copy constructor could be
rather helpful here and IMHO should be considered of being implemented by
MS.

Axel
Daniel O'Connell [C# MVP] - 25 Feb 2006 07:51 GMT
>> Please persist with the virtual method solution if possible as it is much
>> preferable to reflection for a number of reasons.
[quoted text clipped - 11 lines]
> rather helpful here and IMHO should be considered of being implemented by
> MS.

There are some messy things that would have to be dealt with if you added
copy constructors. Right now there is no object slicing, types aren't
defined by their data order(by which I mean you don't have "well, they both
hold an int" to deal with,) the complexity of assignments grows more, and
cloning isn't constrained by the messiness of copy constructors(basically,
since copy constructors aren't polymorphic in nature its quite easy to lose
data, something that isn't currently possible in .NET.)

Add copy constructors and you have a whole host of things that have to be
figured out. Are they allowed strictly for upcasting? What if their are new
fields? How does the compiler deal with dataloss? Do we actually want to
create copies or is it simply another view we are trying to get?

In your case, I get the impression you just want another view. A copy isn't
the right thing to do here, IMHO, since you are wasting memory and
complicating state management(assuming there *is* state management) for no
clear reason. Encapsulation would probably be my first thought(and that
would get you over the explicit conversion problem).
Axel Dahmen - 10 Mar 2006 18:31 GMT
> Add copy constructors and you have a whole host of things that have to be
> figured out. Are they allowed strictly for upcasting?

Well, it would help a great deal if at least upcasting was possible. Just
adding a couple of member functions to a base class (by creating a derived
class with no new fields) should not throw an InvalidCastException.

> What if their are new fields?

Like I said in one of my previous posts: If there are no new fields, then
upcasting will not be a problem because there's nothing added to the object.
This option should be available automatically using no copy constructor.

If there are new fields introduced by the deriving class then an explicit
constructor is required, utilizing a copy constructor, provided by .NET,
like:

 public MyDerivedClass(MyBaseClass baseClass) : base(baseClass)
 {
   ...
 }

plus explicit conversion operator, like:

 public static explicit operator MyDerivedClass (MyBaseClass baseClass)
 {
   return new MyDerivedClass(baseClass);
 }

> How does the compiler deal with dataloss?

There is no dataloss.

> Do we actually want to create copies or is it simply another view we are
trying to get?

Upcasting (= no new fields introduced) is simply another view. Creating a
new class would require a silent and shallow copy.

> In your case, I get the impression you just want another view. A copy isn't
> the right thing to do here, IMHO, since you are wasting memory and
> complicating state management(assuming there *is* state management) for no
> clear reason. Encapsulation would probably be my first thought(and that
> would get you over the explicit conversion problem).

No...

a) encapsulation (=aggregation) will add unnecessary overhead to my
implementation as I would need to provide each and every functionality from
the base class in my derived class just to call my encapsulated member.

b) I can't downcast if I just encapsulate. I need to derive from a base
class.

Axel Dahmen
Daniel O'Connell [C# MVP] - 10 Mar 2006 21:03 GMT
>> Add copy constructors and you have a whole host of things that have to be
>> figured out. Are they allowed strictly for upcasting?
>
> Well, it would help a great deal if at least upcasting was possible. Just
> adding a couple of member functions to a base class (by creating a derived
> class with no new fields) should not throw an InvalidCastException.

It would be nice ocassionally, but I don't think its worth the
compiler\language complexity nor does it seem like something that would be
used consistently. I'm quite sure you should be able to work around it
easily.

>> What if their are new fields?
>
> Like I said in one of my previous posts: If there are no new fields, then
> upcasting will not be a problem because there's nothing added to the
> object.
> This option should be available automatically using no copy constructor.

That isn't the point. It adds complexity. What if there are new fields? What
errors should the compiler emit? How do you make it simple and easy for
everyone to understand? How do you do it in a language independent manner(or
do you?) Is it valuable across a wide range of users? Its alot to consider
for a feature that may only be really useful to C++ developers that dabble
in C# and occasionally useful to the regular C# dev.

> If there are new fields introduced by the deriving class then an explicit
> constructor is required, utilizing a copy constructor, provided by .NET,
[quoted text clipped - 15 lines]
>
> There is no dataloss.

I dislike explicit operators and copy constructors both, so I don't like
this much. Not only does it rewrite some base rules, it has some potential
problems, which I'll address later.

There could also be data loss, quite easily. Consider this scenario which
illustrates why you can't convert a base type to a derived type and where
dataloss can occur:

Considering these classes:

class MyBaseClass
{
   string stringA;
}

class MyDerivedClass : MyBaseClass
{
   void NewMethod();
}

class MyDerivedClass2 : MyBaseClass
{
   string apple;
}

how does this code work out?

MyBaseClass mbc = new MyDerivedClass2();
MyDerivedClass mdc = <MyDerivedClass>mbc;

The copy constructor can lose data and the user wouldn't be able to tell,
especially if MyDerivedClass2 is returned by another component instead of
being constructed right there. You could use a runtime error, but that will
eventually just come down ontop of the end user. It's to easy to mess this
up, probably worse than casting as it stands, which is pretty messy, IMHO.
Someone else will just have the same problem you are, just in a slightly
different way. Language features like this should really be resolvable at
compile time, IMHO.

>> In your case, I get the impression you just want another view. A copy
> isn't
[quoted text clipped - 13 lines]
> b) I can't downcast if I just encapsulate. I need to derive from a base
> class.

You appear to only have one dataset. It'd be pretty simple to build a series
of explicit conversions or constructors from the dataset class to the
functionality class instead of up and down casting.

FilterXClass fxc = new FilterXClass(data);

Also, out of curiosity, have you looked into the proposed extension methods
from C# 3.0[1]? Assuming they survive into the final product, you'd be able
to sort of paste on methods from other classes based on using statements
instead of having to cast around for new functionality. Its kinda ugly, but
it is a possiblity.

1. http://dotnet.org.za/ernst/archive/2005/11/19/48385.aspx
Nick Hounsome - 23 Feb 2006 16:43 GMT
I forgot to mention in my last post that the one way you could acheive the
syntax that you are looking for is by creating an explicit cast operator in
each derived class.

IMHO this is inferior to the virtual method approach as it requires a wasted
temporary base class object.

> Hi Nick,
>
[quoted text clipped - 115 lines]
>> > No, the language doesn't support copy constructors. You'd have to do
>> > MyTypedClass mtc = new MyTypedClass(new MyGenericClass());

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.