[Home]How To Create A New .NET Class

Contents | (Visit Preferences to set your user name.) | Related To How To Create A New .NET Class | RecentChanges | Preferences | Index | Login | Logout

Featured: Featured Stories | Picture Gallery

Lon Chaney | Letter To Jeff Katz Radio Show About The October 2005 Lousiana Police Beating Of Robert Davis
Google
Chat11.com Web Bible11.com MyBibleCenter.com
Search For Books About:
/BottomAd1, ArgumentNullException, Computers, FormatException, Garnet, GetHashCode, InvalidOperationException, Programming, Software, ToString, ToUpper, WriteLine
Search The Net:
Garnet
Computers
Software
Programming
InvalidOperationException
ToString
GetHashCode
ArgumentNullException
ToUpper
FormatException
WriteLine
/BottomAd1
Cover of ISBN 0672323079

Cover of ISBN 0761535225

Java Programming For The Absolute Beginner

Cover of ISBN 0596003471

Programming .NET Components

How To Create A New .NET Class

Subjects > Computers > Software > Programming > Web Application Programming For .NET


Cover of ISBN 1861008287
Cover of ISBN 1861007043

If you moved to C# from VB or another language, you might wonder why the language is so strict in its object-oriented rules. In 'C# Class Design: Coding Effective Classes', you'll learn that in .NET everything is a type and you only can use methods on these types. You must change the way you think about solving problems. Programming used to involve accepting a data type and later checking to see if it is of a certain form, and then have other methods to manipulate that type if you need to.

Now, if you have specific data, in a specific format, it makes sense to create a new type to handle that data and just have your methods/class work on that type. C# additionally allows you to define operator overloads so that once defined, your type can behave in much the same way as you would expect if it were a number or a string.

In the following example program, a new class is created with a few operator overloads in it to show how to use it like a normal type. This is a simple type that represents suits in a pack of cards. It is used to represent what suit is trumps in a Wist game, and so I want to define a plus operator on it that cycles it to the next defined suit on each deal. As an example, the default order will be Hearts, Clubs, Diamonds, Spades. So, on startup a variable holding this value will hold "Hearts". Upon using the addition operator, it becomes Clubs, then Diamonds, then Spades, and then back to Hearts again.

Okay, let's start with the class definition:

using System;

 class Suit
 {
  private const string HEARTS = "Hearts";
  private const string CLUBS = "Clubs";
  private const string DIAMONDS = "Diamonds";
  private const string SPADES = "Spades";

The strings are defined as constants for ease of use.

  public static readonly Suit Hearts = new Suit(HEARTS);
  public static readonly Suit Clubs = new Suit(CLUBS);
  public static readonly Suit Diamonds = new Suit(DIAMONDS);
 public static readonly Suit Spades = new Suit(SPADES);

Now I have defined a few fields that permit me to define the 4 different states this class can have (the four suits).

 private string[] currentSuit;
 int index=0;

The above are the private fields that will store the state. Now the constructors:

 public Suit(Suit position1, Suit position2, Suit position3, Suit position4)
 {
  if(position1.Equals(position2)|| position1.Equals(position3) 
      || position1.Equals(position4) || position2.Equals(position3) 
      || position2.Equals(position4) || position3.Equals(position4))
 throw new InvalidOperationException?Create("Must pass 4 distinct values to the constructor");
 this.currentSuit = new string[] {position1.ToString?Create(), position2.ToString?Create(), 
                                  position3.ToString?Create(), position4.ToString?Create()};
 }

The above just specifies the order of the suit, and that for the order of suits, no suits are repeated.

 private Suit(string suit)
 {
  this.currentSuit = new string[] { suit };
 }

 public Suit() : this(Suit.Hearts, Suit.Clubs, Suit.Diamonds, Suit.Spades)
 {
 }

The above private constructor is only accessed from the constants above, and the public constructor just defines the default order. The class, is almost defined, we'll just specify the ToString?Create(), Equals(), and GetHashCode?Create() operators.

 public override string ToString?Create()
 {
  return this.currentSuit[index];
 }

 public bool Equals(string suit)
 {
 if(suit==HEARTS || suit==CLUBS || suit==DIAMONDS || suit==SPADES)
  return(this.GetHashCode?Create()==suit.GetHashCode?Create());
 else
  return false;
 }

 public bool Equals(Suit suit)
 {
  return(this.GetHashCode?Create()==suit.GetHashCode?Create());
 }

 public override int GetHashCode?Create()
 {
  return this.currentSuit[index].GetHashCode?Create();
 }

Hopefully, the above is quite straightforward. Only one more method to add, and that is the static Parse() method used for parsing a string argument into a Suit class:

public static Suit Parse(string suit) {

 if(suit==null)
  throw new ArgumentNullException?Create("suit");
 suit = suit.Trim().ToUpper?Create();
 if(suit=="HEARTS")
  return Suit.Hearts;
 else if(suit=="CLUBS")
  return Suit.Clubs;
 else if(suit=="DIAMONDS")
  return Suit.Diamonds;
 else if(suit=="SPADES")
  return Suit.Spades;
 else
  throw new FormatException?Create("Value parsed is not one Hearts, Clubs, Diamonds, or Spades");
}

Cover of ISBN 1861008287 Cover of ISBN 1861007043

As you can see, we now have a useful type that behaves as expected and so I can pass a Suit type to the methods in my application and instantly know what is going on. However, I said that I wanted to override the ++ operator to allow me to cycle through the suits. Look below to see how this is done:

public static Suit operator ++(Suit suit) {

 if(suit.currentSuit==null || suit.currentSuit.Length==1)
  return suit;
 suit.index++;
 if(suit.index>3)
  suit.index=0;
 return suit;
}

What this does is simply return the same object an order hasn't been specified (it is one of the readonly fields), or increase the index by one (returning it to 0 if it is higher than 3) and returning itself. This isn't very exciting. You could define a method to do this. However, you can also define implicit and explicit casting operators. Look below:

 public static implicit operator Suit(string suit)
 {
  return Suit.Parse(suit);
 }

 public static implicit operator string(Suit suit)
 {
  return suit.ToString?Create();
 }

With this, I can define a new type by saying: Suit suit = hearts; and I can also use a line like Console.WriteLine?Create(suit); to return the name of the suit. These are very useful to help make your type behave like a value type. You can also override the equality operators so that you can compare this in a more intuitive way. See below:

 public static bool operator ==(Suit suit1, Suit suit2)
 { 
  return suit1.Equals(suit2);
 }

 public static bool operator !=(Suit suit1, Suit suit2)
 {
  return !suit1.Equals(suit2);
 }

Whenever you define an equals operator, you should always define a not equals one. I just use the new methods I defined to do this. We can also do the same if we are comparing this with string objects:

 public static bool operator ==(Suit suit1, string suit2)
 {
  return suit1.Equals(suit2);
 }

 public static bool operator !=(Suit suit1, string suit2)
 {
  return !suit1.Equals(suit2);
 }

 public static bool operator ==(string suit2, Suit suit1)
 {
  return suit1.Equals(suit2);
 }

 public static bool operator !=(string suit2, Suit suit1)
 {
  return !suit1.Equals(suit2);
 }
}

You have to include the cases where strings are before and after the == sign. Now you have a type that you can compare and use like a string, but that will always have predictable values.

You can learn so much more about how to use types effectively in your C# code in the C# Class Design Hanbook from Wrox Press. C# Class Design - Coding Effective Classes'

See also 'Professional C# (2nd Edition)' and 'C# Text Manipulation Handbook' for more information

Cover of ISBN 1861008287 Cover of ISBN 1861007043

Some other articles here about programming web applications for .NET:


Could not find Programming/BottomAd1?Create



Contents | (Visit Preferences to set your user name.) | Related To How To Create A New .NET Class | RecentChanges | Preferences | Index | Login | Logout
Edit this www.chat11.com page | View other versions
Last edited April 8, 2007 2:54 am (diff)
Search:
Sign up for PayPal and start accepting credit card payments
instantly.
Bobsgear - Get A Free Enterrpise Wiki Space!
Review: The Bobsgear Project was started to develop a variety of Confluence plugins. This installation of the Confluence Enterprise wiki includes flexible attachments, many Confluence plugins, personal blogs, interesting articles, and more. Bobsgear already has spaces related to politics, art and photography wiki, technical issues wiki, ediscovery wiki, health, Christian theology and Sabbath School wiki, the bible, book reviews, and quotations. Bobsgear allows free signup, and invites anyone to create a free hosted Confluence wiki space.


NEW USERS CLICK HERE! for a quick introduction to Wiki.

 

 Interested in Sandra Bullock?
438 total hits since 9/2007
Recently accessed pages: Autism Civil Jury Instructions 18.15 On Likelihood Of Confusion Factors And Sleekcraft Test Computer Contents Fryes Electronics Return Policy - Some Comments GarnetRChaney HSI BUAD 105-7310- Introduction To Business HSI BUAD 246-8410- Business Research And Communication HSI HLSC 110-0405- Healthier Living HSI RELB 310-7221- Hebrew Prophets Julia Roberts Lame Jokes Lynn Woolsey's August 2005 Unsolicited Political Email Maintenance Marriage And Constitution Of The Family In Biblical Times Modeling Clay Leisure Clay Problems With Sprint IP-830W Wireless Modem Feature

Elapsed:0