The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

C#, function calls, pointers

I have C++ background, so I dream in pointers and references. I started using C# and the fact that C# is hiding the pointer notation is kinda making me feel uneasy.  :)

All objects are used and passed around with the "." notation etc, so it seems that there are no pointers and references, but does that mean that if I pass an object as an argument to a function, the entire thing is copied? Is the C# compiler smart enough to know when to use references instead of copy constructors?

Of course, I came across "ref" which suggests that it doesn't, and the whole pointer hiding mindset probably causes all sorts of object copying and other kinds of things C++ programmers know to avoid.

So should I just stop worrying about these details? Is there any value in doing so?
newbie_C#
Wednesday, April 16, 2008
 
 
> does that mean that if I pass an object as an argument to a function, the entire thing is copied?

No.

In C#, instances of a class are always passed by pointer. The literature says that it's "by reference", which means that it's "by pointer" with the only difference being syntactic (i.e. in C# you use "." instead of "->" to dereference it); NB that an instance of a class can be null.

In C#, instances of a struct are passed by value. For this reason most of your types should be classes instead of structs, and anything that's a struct should be immutable (i.e. all its data members should be readonly).

> Is the C# compiler smart enough to know when to use references instead of copy constructors?

It always uses references for classes, and copies for structs.

It's hard to make a copy of a class; copying an instance of a class never happens implicitly; instead it will only ever happen if you ask for it explicitly: read the help for object.MemberwiseClone and for the ICloneable interface.

> Of course, I came across "ref"

Using the ref keyword means that instead of passing a pointer by value you're passing the pointer by reference:

///untested code ahead ... test this using the object.ReferenceEquals methods
class Dog
{
 public void Bark() {}

 public static void test(Dog a, Dog b, ref Dog c)
 {
  a.Bark();
  //caller is stll pointing to 'a' which has just barked

  b = new Dog();
  //caller is still pointing to the original 'b'

  c = new Dog();
  //caller is pointing to the new 'c'
 }
}
Christopher Wells Send private email
Wednesday, April 16, 2008
 
 
I suggest that you get a good C# book.

Ok, just "a C# book".

I have "Pro C# with .Net 3.0". It's not terrible and it's weighty enough to make you feel that eventually you'll become an expert.

Tip: Don't learn a language just by intuition from another language.
Daniel_DL Send private email
Wednesday, April 16, 2008
 
 
Larry Lard
Wednesday, April 16, 2008
 
 
> NB that an instance of a class can be null.

I should have said that a pointer or 'reference' to an instance of a class can be null.
Christopher Wells Send private email
Wednesday, April 16, 2008
 
 
I'm going through the same thing trying to learn C# with C++ background.

I know you said untested code, but I do have a question about this though:
> b = new Dog ();
> // caller is still pointing to the original 'b'

When you say that the caller is still pointing to the original 'b,' where does the "new Dog ()" go?

Here is a pretty good book I've been looking through trying to teach myself C#. And the best part about it is that it is free!

http://www.charlespetzold.com/dotnet/index.html
Brian Shipe Send private email
Wednesday, April 16, 2008
 
 
> When you say that the caller is still pointing to the original 'b,' where does the "new Dog ()" go?

class Dog
{
 string Name;

 Dog(string Name) { this.Name = Name; }

 static void caller()
 {
  Dog a = new Dog("Alex");
  Dog b = new Dog("Brian");
  Dog c = new Dog("Charlie");
  Dog.test(a, b, ref c);

  assert(b.Name == "Brian"); //still the original
  assert(c.Name == "Chris"); //changed to a different
 }

 static void test(Dog a, Dog b, ref Dog c)
 {
  b = new Dog("Boris");
  c = new Dog("Chris");

  assert(b.Name == "Boris");
  assert(c.Name == "Chris");
 }

 static void assert(bool b)
 {
  if (!b) throw new ApplicationException();
 }
}
 
I meant that the "new Dog()" assignment DOES change the value of the b parameter within the test function; but, because b is not a ref parameter, there are two distinct copies of the 'b' reference a.k.a. pointer (one in the test function and another in whatever method is invoking test), so the assignment DOES NOT doesn't change the change the value of the reference within the calling function (which still points to the original Dog).
Christopher Wells Send private email
Wednesday, April 16, 2008
 
 
The other posters have this mostly right, but to simplify:

1) C# always passes by value unless you specify ref or out
2) In the instance of reference types, the value passed is the value of the pointer (not a copy of the class)
3) For most intents and purposes, classes behave as if they are passed by reference (which is why most people say they are passed by reference). Changes to an instance of a class are reflected when you exit a method except when you try to replace an instance with another instance (changing the actual pointer reference) which isn't reflected.
4) ref and out are used when you need to pass the pointer as a reference so that you can change it. This allows you to instantiate a new class change the pointer, etc., and have this be reflected outside of the method.

Wednesday, April 16, 2008
 
 
Christopher, I think I get it. Thanks!
newbie_C#
Wednesday, April 16, 2008
 
 
"It's hard to make a copy of a class; copying an instance of a class never happens implicitly"

One reason for this is that an object can contain other objects (which can contain other objects...). How deep or shallow should the clone be?  And what should be done when the object to be cloned  contains references to things like files or windows or hardware?  Only the object knows how to clone itself, via your Clone method.
Jeanne P. Send private email
Wednesday, April 16, 2008
 
 
rtfm

Wednesday, April 16, 2008
 
 
Thanks Christopher.

That makes much more sense now. :-)
Brian Shipe Send private email
Thursday, April 17, 2008
 
 
> rtfm

Yes, I'll get some C# books and take a closer look.
newbie_C#
Thursday, April 17, 2008
 
 
C# is absolutely not the same as C++ just because the two languages look similar.  C# is virtually the same as Visual Basic for .NET, and very similar to Java, but totally different from C++ in practice.

Regarding your other thread, if you want an easy-to-use high-level language that is portable and interfaces well with C your best choice would be Python.  If you just want something that's portable you should use Java.

But if you want to use C++ you should just keep using C++ and forget about other languages -- there's no easy translation between C++ and modern sandbox languages.  And to mix C++ with other languages you either need to go down to the C level (traditional DLLs) or use platform-specific extensions (C++/CLI) or heavyweight solutions like COM/CORBA.
Chris Nahr
Saturday, April 19, 2008
 
 
This comes from Java, not C# specifically, but I'm assuming parameter passing is the same.

All parameters are by value.  For a basic type, like an integer, what is passed is the value.

For an object, the value of the reference (which is something like a pointer) is passed.

So the closest thing to C++ is to think of references, not pointers.

PS: If you've never encountered references to objects in C++, you probably need to get better with C++ as well.
.
Monday, April 21, 2008
 
 
> PS: If you've never encountered references to objects in
> C++, you probably need to get better with C++ as well.

I know of references. What threw me off was the fact that there is the "ref" keyword, but now I realize this is for other "non-new'ed" entities like structs and built-in types.
newbie_C#
Tuesday, April 22, 2008
 
 
Here's a quick translation table:

C# -> C++

Foo f -> Foo &f

out Foo f -> Foo **f, on input f is null

(Actually it's probably Foo *&f or something silly like that, I don't remember my C++ well enough I guess).

when you say

f = new Foo();

 in C# on an out parameter, it's the same as saying:

*f = new Foo();

in C++.

ref Foo f -> Foo **f, f may not be null on input

When you say f.Bar() in C#, in C++ it's the equivalent of saying (*f)->Bar() in C++.

Hope this doesn't confuse even more.

-Chris
Chris Tavares Send private email
Tuesday, April 22, 2008
 
 
This whole debate is pointless because if this person is using C++ and C# in the .NET framework (which is what it sounds like), the CLR and framework manages all those pointers for you. Its all managed code and the CLR will compile all those pointers and calls down to the same assembly language anyway. Microsoft has changed all that so go ahead and use C++ in say Visual Studio and create your builds using the CLR, if thats what you are  comfortable with. Doesnt matter any more. Its whatever language you are comfortable  that matters with in .NET.
Ranger
Saturday, April 26, 2008
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz