Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Just about everything is a heap object when you are using C#. Only elementary native types like int are treated as value types. But there are two value types in C# that are pretty much more useful that first glances would tell you. They are the enum and struct types. Very few tutorials even cover these topics, but they have their own uses. And both of them are a lot more efficient than classes and you can use them in place of classes when they meet your requirements to improve performance.

Enums

Enums are basically a set of named constants. They are declared in C# using the enum keyword. Every enum type automatically derives from System.Enum and thus we can use System.Enum methods on our Enums. Enums are value types and are created on the stack and not on the heap. You don't have to use new to create an enum type. Declaring an enum is a little like setting the members of an array as shown below.

enum Rating {Poor, Average, Okay, Good, Excellent}

You can pass enums to member functions just as if they were normal objects. And you can perform arithmetic on enums too. For example we can write two functions, one to increment our  enum and the other to decrement our enum.

Rating IncrementRating(Rating r)
{
    if(r == Rating.Excellent)
        return r;
    else
        return r+1;
}
Rating DecrementRating(Rating r)
{
    if(r == Rating.Poor)
        return r;
    else
        return r-1;
}

Both functions take a Rating object as argument and return back a Rating object. Now we can simply call these functions from elsewhere.

for (Rating r1 = Rating.Poor; 
    r1 < Rating.Excellent ; 
    r1 = IncrementRating(r1))
{           
    Console.WriteLine(r1);
}

Console.WriteLine();

for (Rating r2 = Rating.Excellent; 
    r2 > Rating.Poor; 
    r2 = DecrementRating(r2))
{
    Console.WriteLine(r2);          
}

And here is a sample code snippet showing how you can call System.Enum methods on our Enum object. We call the GetNames method which retrieves an array of the names of the constants in the enumeration.

foreach(string s in Rating.GetNames(typeof(Rating)))
    Console.WriteLine(s);

Where to use enums

Quite often we have situations where a class method takes as an argument a custom option. Let's say we have some kind of file access class and there is a file open method that has a parameter that might be one of read-mode, write-mode, read-write-mode, create-mode and append-mode. Now you might think of adding five static member fields to your class for these modes. Wrong approach! Declare and use an enumeration which is a whole lot more efficient and is better programming practice in my opinion.

Structs

In C++ a struct is just about the same as a class for all purposes except in the default access modifier for methods. In C# a struct are a pale puny version of a class. I am not sure why this was done so, but perhaps they decided to have a clear distinction between structs and classes. Here are some of the drastic areas where classes and structs differ in functionality.

struct Student : IGrade
{   
    public int maths;
    public int english;
    public int csharp;

    //public member function

    public int GetTot()
    {
        return maths+english+csharp;
    }

    //We have a constructor that takes an int as argument

    public Student(int y)
    {
        maths = english = csharp = y;
    }

    //This method is implemented because we derive

    //from the IGrade interface

    public string GetGrade()
    {
        if(GetTot() > 240 )
            return "Brilliant";
        if(GetTot() > 140 )
            return "Passed";
        return "Failed";
    }
}

interface IGrade
{
    string GetGrade();
}

Well, now let's take a look at how we can use our struct.

Student s1 = new Student();
Console.WriteLine(s1.GetTot());
Console.WriteLine(s1.GetGrade());

//Output

0
Failed

Here the default constructor gets called. This is automatically implemented for us and we cannot have our own default parameter-less constructor. The default parameter-less constructor simply initializes all values to their zero-equivalents. This is why we get a 0 as the total.

Student s2;
s2.maths = s2.english = s2.csharp = 50;
Console.WriteLine(s2.GetTot());
Console.WriteLine(s2.GetGrade());

//Output

150
Passed

Because we haven't used new, the constructor does not get called. Of all the silly features this one must win the annual contest by a long way. I see no sane reason why this must be so. Anyway you have to initialize all the member fields. If you comment out the line that does the initialization you will get a compiler error :- Use of unassigned local variable 's2'

Student s3 = new Student(90);
Console.WriteLine(s3.GetTot());
Console.WriteLine(s3.GetGrade());

//Output

270
Brilliant

This time we use our custom constructor that takes an int as argument.

When to use structs

Because structs are value types they would be easier to handle and more efficient that classes. When you find that you are using a class mostly for storing a set of values, you must replace those classes with structs. When you declare arrays of structs because they are created on the heap, efficiency again improves. Because if they were classes each class object would need to have memory allocated on the heap and their references would be stored. In fact lots of classes within the .NET framework are actually structs. For example System.Drawing.Point is actually a struct and not a class.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionProblem of Event and Delegate
sanjayror
9:00 25 Oct '08  
Sir I'm confused of Event and Delegate.
I do't know how to creat method or etc.
GeneralNewbie Question
akobold
3:15 31 Jan '07  
Hi all, I am really new to C# and I am having a problem with structs.
in C++ it is perfectly common do something like:
struct foo {
int bar[10];
char otherthing[20];
};

but in c# I tried doing:
public struct foo {
int[] bar = new int[10];
byte[] other = new byte[20];
}
but I got the error 'cannot have instance field initializers in structs';
So, how can I have arrays in structs?

AnswerRe: Newbie Question
Kevinyou
6:45 26 May '07  
unsafe struct Foo
{
fixed int bar[10];
fixed char otherThing[20];
}
// not convenient to use.
GeneralHow to load a lot of data into structs?
Brent_Daignault
12:11 14 Oct '05  
Hi Nishant,
One thing that's often overlooked is how to store a bunch of data in a program that will not be changing.

I'm building a coordinate conversion library in C# and would like to store all the various ellipsoid info in the dll, not an XML file or other external file. What would you recommend for a library component.

I plan to use an enum and a struct to define ellipsoids, but with 30 or more, how can I properly initialize all the fields.

enum eEllipsoidType {type1,type2,type3}

struct Ellipsoid
{
eEllipsoidType etype;
double a,b;
}

Then later,
ArrayList alEllipsoid = new ArrayList[];

Will a resource file be useful.

In C++, you can do this, but C# does not allow initialization.Frown
struct
{
double val;
int index;
} DefaultInput[] = {{60,0},{70,0},{20,0},{14.73,0},{2,0},{1,0},{0.6,0},{0.78,0},{1000,0}};

Another example from C++:
const UnitList::Conversion ucTemp[] =
{{"Fahrenheit",1,0},{"Celsius",1.8,32},{"Rankine",1,-459.67},{"Kelvins",1.8,-459.67}};

but again, this is another form of structure initialization.

What is the best practice for including a lot of constant parameter data that will be included in the dll when compiled into a library component.
GeneralProblems with structs in C#
ghost1207
1:11 7 Feb '05  
Hi Nish,

I decided to quit using classes when I wrote the following code:

public struct Demo
{
public string value;
}
ArrayList al = new ArrayList();
al.Add(new Demo);
((Demo)al[0]).value = “Test”;

..and got an error from the compiler: "The left-hand side of an assignment must be a variable, property or indexer" Sigh
I know, I know: an ArrayList pointer is not possible to 'point' to a variable that has been instantiated on the stack (which is the case for structs). Is there any way to overcome this limitation? The only way I found was to copy the Demo in the list to temporary variable, delete it from the list, change its value and re-insert it to list (quite cumbersome!)
Of course if you put "class" instead of "struct" all goes well..

Cheers,
Dimitris
GeneralRe: Problems with structs in C#
Anonymous
7:49 9 Mar '05  
Actually you mean you quit using structs (as opposed to classes).

And personally I don't like using structs either. Usually when you're dealing with data you're dealing with sets of it. So you need to be able to store N of them. And you want to be able to make changes without having to remember to put the changed value back. Lazy? maybe... but I stopped using structs a long time ago.
GeneralRe: Problems with structs in C#
kam18
10:28 14 Aug '06  
in Net 2.0 you can use generics to create collections of structs (this wasn't available when this discussion was started)

for example

List<Demo> demolist = new List<Demo>();
Demo demo1;
demo1.value = 12345;
demolist.Add(demo1);
...
demolist[n].value = ...;

the list is allocated on the heap so it will persist beyond the scope where the added structures were created as long as the reference to it is kept for use. of course this means a lot of copying around when initializing the list since the semantics are still by value so it's better to use a class, but this is possible.
GeneralUsing typedef structs in C# ,C++
arssa2020
10:26 17 Jun '04  
Hi,
i know that typedef structs creates an aliases for a particular struct in C++.
i m trying to convert .h c++ files to a namespace in C#.net so that i use
C++ DLL in my C# application.
one of the structs in C++ is something like
typedef struct mystruct {....} mystruct1, *mystruct2;
since typedef is used, mystruct1 and *mystruct2 are aliases to mystruct.
how can i acheive the same (i.e aliasses in c#)? i can subtitute mystruct1 and *mystruct2 in the C# namespace (which i am creating) by mystruct. but i am not sure if they are used in the DLL?
your help is greatly appreciated. i am new to DLL and C#
thanks
arssa2020@yahoo.com
GeneralDoes know anybody how to extend a enum?
srlopez
5:21 25 Feb '03  
Imagin this code ( with mistakes )
class A
{
enum mynumber { one, two, three } }

class B : A
{
public B()
{
//Does anybody know somme thing similar to this or
// how to do this
base.nynumber.Add( four ); // to use like
int a = mynumber.one;
int b = mynumber.four;
}
}

my question you know, is this or some thing similar possible.
Thanks

Santi
srlopez@rps.es
GeneralRe: Does know anybody how to extend a enum?
Daniel Turini
5:32 25 Feb '03  
Hmmm... Sort of. It won't be an enum, but you can do this:
[edit]This is simplified code, you'll need to implement some conversions and operators, but that's the skeleton[/edit]
struct A
{
public static A one;
public static A two;
public static A three;
}

struct B : A
{
public static A four;
}


I see dumb people
GeneralRe: Does know anybody how to extend a enum?
srlopez
5:40 25 Feb '03  
Thanks... is the same idea, but ... struct in c# can inherits?
I not sure.

GeneralRe: Does know anybody how to extend a enum?
Daniel Turini
5:42 25 Feb '03  
srlopez wrote: Thanks... is the same idea, but ... struct in c# can inherits?
I not sure.
Yes, it can.


I see dumb people
GeneralRe: Does know anybody how to extend a enum?
doohickeywannabeewannabe
12:58 26 Nov '06  
Mate, you cannot subclass structs either. Try your code in VS2005.

Enums are structs and both are subject to this limitation.
GeneralRe: Does know anybody how to extend a enum?
Kevinyou
7:23 26 May '07  
You can't add enum element dynamically, you can use Dictionary, SIMILAR TO enum.

Sample Code:

class ClassA
{
protected Dictionary dic = new Dictionary();
public ClassA()
{
dic.Add("one", 1);
dic.Add("two", 2);
dic.Add("three", 3);
}
}

class ClassB: ClassA
{
public int this[string s]
{
get
{
foreach (KeyValuePair kv in dic)
{
if (kv.Key.Equals(s))
{
return kv.Value;
}
}
return Int32.MinValue;
}
}
public ClassB()
{
dic.Add("four", 4);
}
}

static void Main(string[] args)
{
ClassB b = new ClassB();
Console.WriteLine(b["three"]);
}


GeneralLanguage bug or language feature?
dcbrower
5:26 8 Jan '03  
Thanks Nish for the article! But...isn't it odd that code like the following is legal in C#?
Rating average = Rating.Poor + 1;
This is the syntax that underlies IncrementRating and DecrementRating in your article. It's all perfectly legal C#, and you are careful not to go beyond the defined range. But I gotta ask, Is it a good idea to manipulate enums like this? It's not legal in C++.

I can see two drawbacks, and I bet you can guess what they are. First, there is the maintenance problem that arises when the enum changes. When you amend the Rating enum, you also have to double check that IncrementRating and DecrementRating still work. In the United States at least, the pressure of normal grade inflation will soon require the enum to become:
enum Rating {Poor, Average, Okay, Good, Excellent, Awesome, Fantastic}
That may not be so much of a problem in other parts of the world where education standards are better maintained.Big Grin

Second, the method of incrementing and decrementing enums is not general because enum values don't have to occupy a contiguous range:
enum Rating {Poor=40, Average=60, Okay=75, Good=85, Excellent=92}
Adding and subtracting a constant like 1 will not walk you from one enum value to the next in a case like this. In fact, you will land in a crack:
Rating above_average = Rating.Average + 1; // legal, = 51
What seems strange and inconsistent is that you can assign above_average as shown above, but can't do it directly:
Rating above_average = 51; // error!
So what do you think? Given problems like these, is the C# language flawed with regard to its handling of enum?
GeneralGuess: why no overloading default struct ctor
willtsmith
21:08 4 Jan '03  
Consistency.

All of the value types require that you initialize them before use.

Does anyone out their believe that int or char should have a default value.

int i;
char c;

Console.WriteLine( "Int i is {0}, Char c is '{c}'" );

--------------
Output

Int i is 0, Char c is 'a'

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

Obviously, assumptions like this could lead to problems.

Uninitialized value types have always been a problem in C/C++ programming. C# simply doesn't allow them. I believe that the behavior produces a consistency across ALL value types.

Uninitialized reference types default to null. Value types must be assigned before use, no nullness (as far as the compiler is concerned).



Will T Smith
GeneralYou rock Nish
Paul Watson
8:57 4 Nov '02  
I needed to enumerate through an Enum and could not figure it out. I then remembered your article and just knew you would have an example in here as to how to do it. An voila, you did, I did and it rocked! Big Grin

thanks again Nish.

Paul Watson
Bluegrass
Cape Town, South Africa

Ray Cassick wrote:
Well I am not female, not gay and I am not Paul Watson
GeneralRe: You rock Nish
Nishant S
15:18 4 Nov '02  
Thanks Paul Smile

I guess you now qualify as one of the most vociferous supporters of my articles.

Nish


Author of the romantic comedy Summer Love and Some more Cricket [New Win]
Review by Shog9 Click here for review[NW]
GeneralRe: You rock Nish
Paul Watson
20:13 5 Nov '02  
Nishant S wrote: I guess you now qualify as one of the most vociferous supporters of my articles.
Do I get a badge? Smile


Actually I am quite suprised and appalled at the low rating this article has recieved. Sure it is not some revelation of great altruistic knowledge, but it really explains some fundamental concepts very well and provides great samples.

I wish we could see who voted what for what article Big Grin Then we can go pester the low-voters and ask them "Why?"

Paul Watson
Bluegrass
Cape Town, South Africa

Ray Cassick wrote:
Well I am not female, not gay and I am not Paul Watson
GeneralBest practice of using enums and a data source
Paul Watson
6:18 17 Oct '02  
Another question Big Grin

Basically I have an XML file which persists certain data and I guess really represents a class... (maybe I should just serialise my objects? hmm...)

The class has an enum (same as my previous question) with those three "constants", Article, Image and Other. Now in the XML file there is an attribute named type and it holds either Article, Image or Other.

Currently when I pull from the XML file I am using a switch block to assign the right enum "constant" to the object instance. e.g. (pseudo code) If xmlnode.type = "article" then cItem.type = ContentType.Article
I think that is pretty lame and it will get out of hand when more content types are introduced.

So my question is: Is there a better way to do it? Is there a way to sort of "inform" the system that Article in the XML file is equal to ContentType.Article?

There must be, because that will just make enums rock even more! ta (hope my question does not sound too stupid Big Grin )

Paul Watson
Bluegrass
Cape Town, South Africa

GeneralRe: Best practice of using enums and a data source
Nishant S
6:58 17 Oct '02  
Paul,

See this code :-

enum Rating {Poor, Average, Okay, Good, Excellent}
class Class1
{
[STAThread]
static void Main(string[] args)
{
for(Rating r = Rating.Poor; r<=Rating.Excellent; r++)
Console.WriteLine((int)r);
}
}

It'll show 0,1,2,3,4 on screen. So basically they are integeres starting from 0 (unless you specify otherwise).

So perhaps you could do this in your XML :-

<blah type=x />
where x is an integer. Now simply read this x and cast it to ContentType.Article. That should work. This is clearer from the following code snippet :-

Rating q = (Rating)3;
Console.WriteLine(q);

This will output "Good" on the screen.

If my solution sounds silly, well sorry about that Paul. Gave it my best shot Smile

Nish


Author of the romantic comedy Summer Love and Some more Cricket [New Win]
Review by Shog9 Click here for review[NW]
GeneralRe: Best practice of using enums and a data source
Paul Watson
7:13 17 Oct '02  
Nishant S wrote: If my solution sounds silly, well sorry about that Paul. Gave it my best shot
LOL Nish, no your solution was certainly an answer and one I did not think of (do you have a backpack to carry your extra brain btw? Wink )


The only thing is that that means I have to use numbers instead of text in the XML file, which just makes the XML file harder to read and understand outside of the application.

I guess what I have to do is do what you suggested above and then create an XML Schema which has it's own enum defining 1 as Article, 2 as Image etc. It is actually a better way, but damn that is going to take me some time to do and I was hoping for a lazy-ass-programmer way Big Grin

Paul Watson
Bluegrass
Cape Town, South Africa

GeneralRe: Best practice of using enums and a data source
James T. Johnson
15:40 17 Oct '02  
Paul Watson wrote: The only thing is that that means I have to use numbers instead of text in the XML file
You can use the Enum.Parse method to convert the text value back to the enum value.

Untested code follows Wink

enum Foo
{
Bar,
Baz
}

....

Foo foo = (Foo) Enum.Parse(typeof(Foo), "Bar", true);
The first parameter is the Type representing the enum, the second parameter is the string version, and the third parameter tells the method if it should ignore case.

It will throw an Argument exception if "Bar" isn't a valid member of the enum.

HTH,

James
Sig code stolen from David Wulff

GeneralRe: Best practice of using enums and a data source
Nishant S
16:27 17 Oct '02  
Brilliant suggestion Jambo! Paul's XML readability issue is now completely sorted out I guess Smile

BTW the sig is nice; who is he anyway, the guy with the hair-quotes?

Nish


Author of the romantic comedy Summer Love and Some more Cricket [New Win]
Review by Shog9 Click here for review[NW]
GeneralRe: Best practice of using enums and a data source
James T. Johnson
16:54 17 Oct '02  
Nishant S wrote: BTW the sig is nice; who is he anyway
He's one of the major participaters on DevelopMentor's DOTNET-* lists. He certainly has a way with words Smile

James
Sig code stolen from David Wulff


Last Updated 14 Oct 2001 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010