Naming structs with a variable

M

Marty

I am new to C# and to structs so this could be easy or just not
possible.
I have a struct defined called Branch
If I use Branch myBranch = new Branch(i); // everything works
If I use Branch (myBranch + x) = new Branch(i); // it doesn't

x is a loop iterator, i is an int for the constructor to define an
array.

What am I doing wrong here.
 
B

Bruce Wood

First of all, make Branch a class, not a struct.

Second, I'm not sure exactly what you're trying to do in the second
line. If you're trying to initialize an array of Branch'es, then you
need something like this:

int branchArraySize = 20;
Branch[] branchArray = new Branch[branchArraySize];
for (int i = 0; i < branchArray.Length; i++)
{
branchArray = new Branch(i);
}

The second line declares and creates an array of references that could
point to Branch'es, but the array is empty: each entry is null, so
there are no actual branches stored in it yet.

The line inside the loop creates a new Branch object for each entry in
the array and assigns the array entry to refer to that new Branch that
was just created.

Is that sort of what you wanted to do?
 
M

Marty

Thanks for the reply.
What I have is a bunch of comma delimited text files for a source. They
have many "Branches" of various lengths. I don't know how many branches
or how long each branch is because they are all different. What I am
trying to end up with is an instance of a Branch for each branch in the
file. My definition of branch contains an array (array(length,3)) that
gets set to the length of the branch. Something like this:

Branch1, length
item1, item2, item3
item1, item2, item3
item1, item2, item3
Branch2, length
item1, item2, item3
item1, item2, item3
Branch3, length
item1, item2, item3
item1, item2, item3
item1, item2, item3
item1, item2, item3
item1, item2, item3
And so on ...

When I read the start of a branch I create a branch instance. Then I
fill the array in that instance with the info for each line. So I
figured in all my infinite wisdom that I could create a new Branch
struct every time I hit the start and use my iterator to name that
struct. Hence the name (MyBranch + x). Then I could work on the data in
each randomly.
I chose to use structs because I only need to store information of each
branch and I don't need any inheritance properties of a class. But if I
need to use a class or that's better I will, it was just one of those
newbie choices I made reading a book.
 
G

Guest

I'd do what Bruce suggested, except add each branch to a Hashtable. then you
can make the Key of each item correspond to your expected "Branch"
+i.ToString() nomenclature and you don't need to worry about array bounds.
I'm not sure why Bruce suggested using a class instead of a struct.
Peter
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

If the only member variable in Branch is the array, it doesn't really
matter if you use a class or a struct, as long as you don't try to
replace the array with a new array.

I would make it a class, though, and add useful things to it like an
AddItems method.

Use a list to keep track of the Branch instances. If you use framework
1.1 you would use an ArrayList (list of Object). In framework 2.0 you
can use generics to make a type safe list:

List<Branch> branches = new List<Branch>();

Now you can add branches to the list:

Branch branch = new Branch(i);
branches.Add(branch);
 
B

Bruce Wood

First of all, make Branch a class, not a struct.
I'm curious -- why did you advise that?

I will reply to this later. I just typed a long, detailed explanation
and then hit the Windows Start key instead of Alt, and blew it all
away. I'll retype it after I do some research on how to disable that
&*(%$ key that I've never used and always hoses me. Grrrr.....
 
J

Jon Skeet [C# MVP]

Lucian Wischik said:
I'm curious -- why did you advise that?

I suspect it's because class is almost always a wise "default" to take
- creating your own custom struct is very rarely required, and value
type semantics can often cause confusion. (Admittedly reference type
semantics can also cause confusion...)

I can only remember a single struct I've written, and that was for
performance reasons (where it was actually justified, just for a
change).
 
B

Bruce Wood

OK... let's try this again.
I'm curious -- why did you advise that?

For two reasons.

First, remember that structs are value types in .NET. That means that,
like an int or a double, they are copied on every assignment, copied
onto the stack to pass as arguments, and copied onto the stack when
returned as method or property results. This makes perfect sense for
ints, doubles, and even DateTimes: I have never run into a situation in
which I want to change every single variable in my program that holds
the value 5 to now hold the value 7. Every variable has its own copy of
the value, and changing one variable doesn't affect any other one. In
fact, for most values "changing the value" makes no sense at all: to
change what a variable holds you assign a new value.

Is this the kind of behaviour that is appropriate for something like a
"Branch"? Branches have identities: you can sensibly talk about "Branch
15" in our company. When I change some quality of Branch 15, it's
perfectly reasonable to assume (or desire) that every other variable
that holds (a reference to) Branch 15 will see that change as well. Do
I want a Branch to be copied on every assignment, copied onto the stack
for method calls, and copied onto the stack for method returns? Do I
want a system in which it's impossible, or near-impossible to have a
change to a Branch 15 stored in one variable affect the Branch 15
that's held by other variables in other parts of my system? I don't
think so.

..NET structs are tremendously useful in rare cases. In those
particular, peculiar situations they are indispensible. In almost every
other situation they are unnecessary. I see nothing in this problem
that says that the OP's Branch type is one of those rare circumstances
in which value semantics are useful. As Jon said, classes (that is,
reference semantics) should be the default choice. structs (value
semantics) should be employed only when there's a compelling reason to
do so. I see no such reason here.

However, I said that there were two reasons.

The second is that the OP self-identified as a newbie. IMHO,
programmers new to .NET should steer far clear of structs. They are
very, very unlikely to run into one of those rare circumstances in
which value semantics are a good idea. They are much, much more likely
to misapply structs and then wonder why their programs act strangely.
At best this will result in some confusion followed by a decision to
use classes instead; at worst this will result in the incorrect
conclusion that C# makes no sense and therefore sucks.

Take the OP's problem, for example. Göran suggested using an ArrayList
to hold the Branches. This is the simplest design, especially for a new
programmer to follow. Imagine the OP's confusion when they design their
Branch like this:

public struct Branch
{
private int _id;
private ArrayList _itemList;

public Branch(int branchId)
{
this._id = branchId;
this._itemList = new ArrayList();
}

public AddItem(string item1, string item2, string item3)
{
string[] items = new string[3];
items[0] = item1;
items[1] = item2;
items[2] = item3;
}
}

Again, a simple, straightforward design. With one catch: imagine the
OP's surprise when this doesn't work:

public static void Main()
{
ArrayList branchList = new ArrayList();

... some sort of loop to read branches here ...
Branch aBranch = new Branch(id);
branchList.Add(aBranch);
... some sort of loop to read items here ...
aBranch.AddItems(item1, item2, item3);
}

Imagine the consternation when the OP discovers that all of the
branches in the array list have zero items attached to them. Why? What
happened? What kind of stupid language is this, anyway?

Change "public struct Branch" to "public class Branch" and it works.

Experienced .NET programmers with a firm grasp of value semantics
versus reference semantics will, of course, be able to figure out why.
Newbie programmers will, generally speaking, not... not without alot of
pain and research.

If you want to read more about struct versus class, see the following
threads:

http://groups.google.com/group/micr...ges.csharp/browse_frm/thread/a13bcc64b8438f65

http://groups.google.com/group/micr...ges.csharp/browse_frm/thread/e7862a7d7d6a914c
 
B

Bruce Wood

Sorry. In my haste I wrote the Branch struct incorrectly. The correct
code follows:

public struct Branch
{
private int _id;
private ArrayList _itemList;


public Branch(int branchId)
{
this._id = branchId;
this._itemList = new ArrayList();
}

public AddItem(string item1, string item2, string item3)
{
this._itemList.Add(item1);
this._itemList.Add(item2);
this._itemList.Add(item3);
}
}
 
B

Bruce Wood

Sigh. I even gave an incorrect link at the bottom of my post. I'm
having a bad day.

Just search this newsgroup for "struct vs class". You'll get lots of
hits.
 
M

Marty

Seems to work good so far. I have alot more to do yet.
I used a Hashtable to store the objects created by my class in.
I can reference any Branch I need at any time with a little code.
Now I need to learn a little recursion, another head swimmer. Maybe a
loop will work better.

Some good information here. Thanks!
 
B

Bill Butler

OK... let's try this again.
I'm curious -- why did you advise that?

<Snip an excellent explanation of why to prefer class over struct>

Nicely written Bruce.
I find that this is a MAJOR source of confusion for the C/C++ folks (I
was one of them).
They tend to think of structs as lightweight classes.
Perhaps struct was not such a good name for these thingamabobs.
Oh well, Nice job
Bill
 
C

Chris Nahr

I find that this is a MAJOR source of confusion for the C/C++ folks (I
was one of them).
They tend to think of structs as lightweight classes.
Perhaps struct was not such a good name for these thingamabobs.

I don't see the confusion here. Structs _are_ lightweight classes in
C#, as opposed to C++ where struct is just another name for class that
implies a different default visibility.

The problem is that the mechanism that provides for this
lightweight-ness has a few gotchas that C++ people will miss.
 
B

Bruce Wood

Structs _are_ lightweight classes in C#.

Sorry. I categorically disagree with this. I agree with Bill: maybe
"struct" wasn't such a good keyword.

Structs are "lightweight" only in the sense that they avoid garbage
collection, but that's a consideration only when they're used in
massive numbers. That's why (IMHO) Microsoft chose to make Point and
Rectangle as structs rather than as classes: because they anticipated
that they would be used in massive numbers, and they wanted to avoid
the consequent overhead allocating and collecting them off the heap.

However, structs are _heavyweight_ where assignment, argument passing,
and method/property returns are concerned. It is possible to _degrade_
the performance of your program by changing classes to structs because
of all the consequent copying.

So saying that structs are "lightweight classes" is misleading: using a
struct may lead to performance gains, or may lead to performance
losses.

For my part, I find that the whole "efficiency" / "lightweight versus
heavyweight" arguing is way down the list of reasons why you would want
to make something a struct rather than a class. It is far, far more
common to want a struct because you want _value semantics_, because the
thing you're making really should act like a value, not distinct
objects each with its own identity. That's why I cringe when I hear it
said that structs are "classes-lite": while there is some truth in that
statement (with the aforementioned caveats), it omits the principal
reason why you would choose one over the other.
 
A

Alvin Bruney

Structs are "lightweight" only in the sense that they avoid garbage
collection,

There's more right? like a failure to participate in inheritance etc. When
viewed from that perspective, it is lighter than a class. Lighter is a good
choice of words because it means that there is enough similarity so that the
struct is not a totally new entity but enough difference such that it does
bring benefit. Here is a complete light definition that works well
http://www.jaggersoft.com/pubs/StructsVsClasses.htm#inheritance differences

--

________________________
Warm regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
Professional VSTO.NET - Wrox/Wiley
The O.W.C. Black Book with .NET
www.lulu.com/owc, Amazon
Blog: http://www.msmvps.com/blogs/alvin
-------------------------------------------------------
 
B

Bill Butler

Chris Nahr said:
I don't see the confusion here. Structs _are_ lightweight classes in
C#, as opposed to C++ where struct is just another name for class that
implies a different default visibility.

The problem is that the mechanism that provides for this
lightweight-ness has a few gotchas that C++ people will miss.

Ahhhh, but that is exactly my point.
In C++, even though classes and structs only differ in their default
visibility, they tend not to be used interchangeably. Structs tend to
be used when the developer doesn't need inheritance (data holders).
There is no good reason to prefer the struct over the class, but it does
seem to be the convention.
So these well meaning developers come to C# and use structs just like
they do in C++ and they get weird behavior. Take for example
MyStruct * mystruct = new MyStruct(); //C++
MyStruct mystruct = new MyStruct(); //C#

In C++ the return from new is a pointer to the object. You get reference
semantics when you construct a struct with the new operator. If you had
wanted value semantics you would have instantiated it without new
MyStruct mystruct; // C++
In C++, you created a MyStruct (called a c'tor and everything)
The same statement in C# gets you an uninitialized reference.

In C++ it is a piece of cake to switch between value an reference
semantics.

MyStruct mystruct;
Foo(mystruct); // copies the struct
Mystruct * pStruct = &mystruct;
Bar(pStruct ); // just passes the pointer;

C# classes and structs *Feel* alot like their older brethren at a casual
glance. It is natural to assume that they will behave similarly. The
inherent "Valueness" of the C# structs is a BIG gotcha to C++ ---> C#
convert.

This is why I feel that it is a good idea to avoid structs until you
understand the pitfalls.

Bill
 
J

Jon Skeet [C# MVP]

There's more right? like a failure to participate in inheritance etc. When
viewed from that perspective, it is lighter than a class. Lighter is a good
choice of words because it means that there is enough similarity so that the
struct is not a totally new entity but enough difference such that it does
bring benefit. Here is a complete light definition that works well
http://www.jaggersoft.com/pubs/StructsVsClasses.htm#inheritance differences

That's a great page, but it doesn't mention the word "light" anywhere.

Structs aren't "lighter" than classes - they're just different. Lighter
is *not* a good choice of words, because it makes people think that
when they need something to be efficient, they should pick a struct.
That's a really, really bad reason to choose a struct unless you're
*very* clean on all the consequences.

Value semantics versus reference semantics can't be reduced to
"lightweight" or "heavyweight", and doing so just causes confusion.
I've seen lots of people choose structs because they're supposedly
lightweight, without understanding what's going on at all, or why they
can *sometimes* bring efficiency benefits along with the other semantic
differences.
 
C

Chris Nahr

Structs aren't "lighter" than classes - they're just different. Lighter
is *not* a good choice of words, because it makes people think that
when they need something to be efficient, they should pick a struct.

But they should! That's a correct description! Microsoft introduced
structs in the first place because they are more efficient than
classes for small data containers such as numerical types, and they
are more efficient because their implement is in fact comparatively
lightweight -- no heap allocation (for locals), no object wrapper.

What you guys are talking about are really just faulty assumptions on
the part of programmers who believe in silver bullets and don't stop
to think "gee, if structs are all-around better than classes then why
do classes exist at all?".

Because once you do stop to ask yourself that question it's pretty
blatantly obvious that a lightweight class is going to have _some_
disadvantage that prevents it from being used universally...

There's a lot to learn when you switch from C++ to C#. The meaning of
"struct" is just one part of it, and not a particularly difficult one
IMO. Maybe it can serve as a useful reminder that the C++ language
has not in fact monopolized the naming and semantics of all
programming constructs, the belief of its fans to the contrary. :)
 
J

Jon Skeet [C# MVP]

Chris Nahr said:
But they should!

No, they shouldn't. They should consider whether they want reference or
value semantics, work out how large the type will be, find out whether
it's actually going to be a bottleneck anyway, whether making it a
value type will actually make it more efficient, etc.
That's a correct description!

No, it's not. They're different beasts, and calling one a lightweight
version of the other doesn't in any way convey the important
differences between them.

There's a lot to learn when you switch from C++ to C#. The meaning of
"struct" is just one part of it, and not a particularly difficult one
IMO.

I agree it's not very difficult, but it's not aided in any way by
calling structs lightweight classes, any more than learning the
differences between int and float would be aided by calling int a
lightweight float.

In short, I haven't seen that description do any *good*, but I've
certainly seen it confuse people before now.
 

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