Click here to Skip to main content
Click here to Skip to main content

Persistent String Parser

By , 21 Dec 2008
 
Screenshot - qstringparser.png

Introduction

Well, I'm finally dragging myself kicking and screaming into the world of C# and .Net. I've decided that in order to stay employable, I have to move away from C++. Toward that end, I recently accepted a C# programming position, and since I didn't want to start a new job cold, I figured I'd get some additional C# experience by porting one or more of my C++/MFC articles to the .Net platform.

Update 21 Dec 2008: A recent comment about this code caused me to revisit it and resulted in a substantial rewrite of the class in question. This article and the downloadable code have been updated to reflect these changes.

What the StringParser Class Is

Essentially, the StringParser class accepts a delimited string, breaks it down into its delimited elements according to the specified delimiter string (or character), and stores it in a string list. You can also add to, insert into, or delete fro the list of parsed elements. Further it supports quoted strings. While you might be inclined to say say that the string.Split() method does the same thing, I agreee - to a point. It does indeed allow you to split a string using a character or a string as a delimiter, but it doesn't support quoted elements, nor does it (readily) provide a method for changing the list of elements.

Personally, I don't see much use for a delimiter string, but someone requested such a feature in my original MFC/VC6 article, and the string.Split() method provides the functonality, so I figured I'd give it a shot in this version of the class. Another new feature (over and above what was provide din the C++ version of the article) is that when deleting a field, the programmer has the choice of deleting all instances of a given string, the first instance, or the last instance.

In the original version of this article, I put the class into a class library project because it seemed to be the right thing to do, but for the most recent version, I put it into the executing assembly just to keep things simple.

One item of note - this class is CLS compliant, so it can be put into its own asembly and used by any language supported by dotNet.

The StringParser Class

The class itself isn't really that fancy, and can essentially be considered a wrapper around the string.Split() method. The real action happens in the Parse() method:

protected int ParseString(string text)
{
    // split the string according to the specified delimiter
    string[] parts = text.Split(m_delimiter.ToCharArray(), StringSplitOptions.None);
    string combinedParts = "";
    bool quoted = false;

    // add each item to the list
    foreach (string part in parts)
    {
        // if the current part contains a quote character, we're building a 
	// multi-part list item, so turn on our tracker
	if (CharacterCount(m_quoteChar, part) == 1)
	{
	    quoted = (quoted) ? false : true;
	}

        // add the part to the combined word
	combinedParts += part;

        // if we're working on a quoted string, add a delimiter character to the 
        // end of the current combined parts.
        if (quoted)
        {    
            combinedParts += m_delimiter;
        }

        // if we're no longer building a combined part, add the current combined 
        // part to the list of elements, and reset the combinedPart variable.
        if (!quoted)
        {
            m_elementList.Add(combinedParts);
            combinedParts = "";
        }
    }

    return m_elementList.Count;
}

This version of the method is MUCH shorter than the original one because dave.dolan recently informed me of the fact that the string.Split() method supports delimiter strings. This in turn caused me to re-evaluate the code, and I came up with a much lower-impact version and fixed a quote string bug in the process. In a nutshell, the method splits the string according to the specified delimiter character, and the adds the individual parts to the internally maintained list. If the string is a quoted string (and if the StringParser object was told to handle quoted strings), the previously split parts are re-combined to for the quoted string.

Note: In the interest of maintaining an accurate historical record, I left the original download in this article, and added a new downoad with the much-improved code. The original code is an embarassment, but I think it's important for new programmers to see how important it is to become as familiar as possible with the dotNet framework as possible.

The Sample Application

The sample application took three times longer to write than the actual class (again, due entirely to my lack of exposure to the .Net framework. There's no real validation being done, so if you experience any quirks, let me know and I'll try to post updated code. Better yet, be a programmer, fix them yourself, and then posrt your findings here.

Class Reference

namespace StringParserLib
{
    public enum eDeleteAction { DeleteAll, DeleteFirst, DeleteLast };

    /// <summary>
    ///  Persistent string parser by Paddedwall Software. 
    /// </summary>
    public class StringParser
    {
        // Properties
        public List<string> Elements
        public string Delimiter
        public char QuoteCharacter


	// Constructors
        //--------------------------------------------------------------------------------
        /// <summary>
        /// Constructor - use this one when you don't yet know the string to be parsed. 
        /// It is assumed that the delimiter will be a comma, and the string is not 
        /// quoted.
        /// </summary>
        public StringParser()

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Constructor - use this one when you DO know the string to be parsed, and 
        /// you want to use the default delimiter of ",".
        /// </summary>
        /// <param name="value">The string to parse</param>
        public StringParser(string value)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Constructor - use this one when you DO know the string to be parsed, and 
        /// you only need to specify the delimiter for a non-quoted string.
        /// </summary>
        /// <param name="value">The string to parse</param>
        /// <param name="delimiter">The delimiter string</param>
        public StringParser(string value, string delimiter)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Constructor - use this one when you DO know the string to be parsed, and 
        /// want to specify the delimiter AND the quote character.
        /// </summary>
        /// <param name="value">The string to parse</param>
        /// <param name="delimiter">The delimiter to use</param>
        /// <param name="quote">The quote character to look for (only needed if the 
        /// string contains quote characters that you want to honor)</param>
        public StringParser(string value, string delimiter, char quote)


        // Protected Methods

       //--------------------------------------------------------------------------------
        /// <summary>
        /// Initializes the data members and allocates the string array
        /// </summary>
        protected void ProtectedInit()

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Removes all of the items from the string array
        /// </summary>
        protected void Clear()

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Returns true if the specified index is a valid index into the array.
        /// </summary>
        /// <param name="index">The index to check</param>
        /// <returns>True if the specified index is within the valid range</returns>
        protected bool IndexInRange(int index)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Does the actual parsing work
        /// </summary>
        /// <param name="character">The charecter to look for</param>
        /// <returns>The number of fields parsed</returns>
        protected int ParseString(string text)


	// Public Methods

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Clears the list, resets the delimiter and quote character, and the 
        /// re-parses the string
        /// </summary>
        /// <param name="value">The string to parse</param>
        /// <param name="delimiter">The delimiter to use</param>
        /// <param name="quote">The quote character to look for (only needed if the 
        /// string contains quote characters that you want to honor)</param>
        /// <returns>The number of fields parsed</returns>
        public int ResetOriginalString(string text, string delimiter, char quote)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Rebuilds the original string by cycling through the array list.
        /// </summary>
        /// <returns>The original string used to create the element list</returns>
        public string ReassembleOriginalString()

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Retrieves and returns the string at the specified index
        /// </summary>
        /// <param name="index">The index of the desired field</param>
        /// <returns>The field at the specified index</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public string GetField(int index)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Retrieves the string at the specified index, and strips the specified string
        /// before returning it to the calling function.  This method is useful for 
        /// removing quotes.
        /// </summary>
        /// <param name="index">The index of the desired field</param>
        /// <param name="delimiter">The text to remove from the returned value</param>
        /// <returns>The field at the specified index</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public string GetField(int index, string textToRemove)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the index of the desired string regardless of case.
        /// </summary>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        public int Find(string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the index of the desired string regardless of case.
        /// </summary>
        /// <param name="startingIndex">The index at which to start the search</param>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public int Find(int startingIndex, string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the index of the desired string - case sensitive.
        /// </summary>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        public int FindExact(string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the index of the desired string - case sensitive.
        /// </summary>
        /// <param name="startingIndex">The index at which to start the search</param>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public int FindExact(int startingIndex, string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the string regardless of case, starting at the last element.
        /// </summary>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        public int FindReverse(string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Finds the exact string, but starting at the last element - case-sensitive.
        /// </summary>
        /// <param name="textToFind">The text we're looking for</param>
        /// <returns>The index of the desired field</returns>
        public int FindReverseExact(string textToFind)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Adds a new string to the array and resets the origial string to include the
        /// new field. It's okay if the string is empty.
        /// </summary>
        /// <param name="textToAdd">The text we want to add</param>
        public void AddField(string textToAdd)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Insert the specified string at the specified inded in the array list. Since
        /// exceptions are pointless here, we'll normalize the specified index so that this
        /// function doesn't insert the string at element 0, or if oustide the current
        /// range, simply adds it to the end of the array.  The return value indicates
        /// where in the array, the item was inserted or added.  If the return value isn't
        /// the same as the specified index, the calling function passed in an invalid
        /// value.
        /// </summary>
        /// <param name="index">The index at which to insert the new string</param>
        /// <param name="textToInsert">The text to insert</param>
        /// <returns>The index at which the string was inserted</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public int InsertField(int index, string textToInsert)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Deletes the specified array list element, and returns true if the deletion was 
        /// successful.
        /// </summary>
        /// <param name="index">The index to delete</param>
        /// <returns>True if the item was deleted</returns>
        /// <exception cref="IndexOutOfRangeException"></exception>
        public bool DeleteField(int index)

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Deletes the specified array list element, and returns true if the deletion 
        /// was successful. 
        /// </summary>
        /// <param name="textToDelete">The index string to delete</param>
        /// <param name="exactMatch">The index at which to insert the new string</param>
        /// <param name="deleteAction">How to delete the item (first occurance, last 
        /// occurance, or all occurrances)</param>
        /// <returns>True if the item was deleted</returns>
        public bool DeleteField(string textToDelete, bool exactMatch, DeleteAction deleteAction)

    } 
}
</string>

As you can see, the class is fairly straightforward, and using it is a simple matter for even the most novice of .Net programmers (and don't forget - it's CLS compliant).

Change History

21 Dec 2008 (update inspired by comment from CP user dave.dolan - Thanks Dave!)

  • Significant change to StringParse method. It's much shorter, and much more reliable.
  • Proper XML comments added.
  • The original string is no longer stored in the object, so all GetField calls are now zero-based (the old version was one-based).
  • Added new constructor overloads.
  • Added new Find and FindExact overloads that let you start the search at a specified index.
  • Added proper exception handling.

31 Jul 2007 - (based on comments submitted after initial article upload)

  • Changed class to use .Net naming convention
  • Renamed namespace and class to comply with first change describe above
  • Eliminated hungarian notation (I feel somehow dirty as a result)
  • Changed from using ArrayList to generic List
  • Changed function comments to Intellisense-compatible summary tags
  • Moved enum declaration outside the class
  • Changed demo app to use .Net naming convention, including control names.
  • Changed demo app to provide basic validation.

30 Jul 2007

  • Original article.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

About the Author

John Simmons / outlaw programmer
Software Developer (Senior)
United States United States
Member
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.
 
My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralHungarian Notation Discussion 1000thmemberjohannesnestler21 Dec '08 - 22:39 
Allways the same discussion about this topic... But I can't resist to share my opinion.
 
I'm C++ and C# developer and I use different prefixing for each language. What I use for C# is not really HN but it leads to the same benefit:
 
* Code is not only seen in an IDE - it's text, so sometime it is printed or seen in an text editor which doesn't "know" about "Code".
* The m_ or _ or m (or whatever you use) prefix is very common. When I look at the Code of my junior developers I think it helps them a lot. The newbies are often confused by variable scope.
* I do a lot of GUI programming (Sometimes several hundred Controls on a Form (Cause of the Framework we use)). So I use a prefixing Schema for the Controls too. Benefit: All Controls of the same type are together in the Intellisense - same with all Variables of the same type if you use a prefix!
 
So .NET style-guide is a most time a good thing but on HN i TOTALLY DISAGREE! I think what is really important in programming is a very strict style you use for yourself. This helps a lot to decide what variable names to use. I have no problem thinking about knew "names" after a type conversion or something similar. And it's easier to spot wrong conversions (iVariable = fVariable)
Think about it ...
 
string strError;
int iError;
Exception exError;
 
string strLine;
string[] astrLine = strLine.Split(",".ToCharArray());
 
Poke tongue | ;-P
GeneralRe: Hungarian Notation Discussion 1000thmvpJohn Simmons / outlaw programmer21 Dec '08 - 23:08 
This article is not the place for this this discussion since it isn't about this article. Please take this to the appropriate forum on the site.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Hungarian Notation Discussion 1000thmemberjohannesnestler21 Dec '08 - 23:13 
Yes you are right. Sorry. I just wanted to answer to the "Improvement" discussion on this article. Rose | [Rose]
GeneralYou don't need to write this. The framework has most of these features already.memberdave.dolan7 Nov '08 - 10:19 
I realize that you're coming from C++, but honestly, this whole class is obviated by stuff that's readily available in the framework. I'm not against baking one's own, but when you don't have to, I wouldn't recommend doing so.
 
 
 //you can do all this stuff with the framework, and basically no extra code.

  string original = "foo,bar,baz,bally,bot";
 
  List<string> foozle = new List<string> ( original.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) );
 
  if (foozle.Contains("bar"))
     Console.Out.WriteLine("It's got a bar!");
 
  int index = foozle.IndexOf("bally");
  
  Console.Out.WriteLine("bally is at position {0}", index);
 
  foozle.Remove("foo");
 
  // look, sorted, for free
  foozle.Sort();
 
  // backward.
  foozle.Reverse();
  
  // iterate
  foreach( string s in foozle) 
  {
          Console.Out.WriteLine("Found: {0}", s);
   }
 
  // join
  string newOriginal = string.Join( "," , foozle.ToArray());
 
  Console.Out.WriteLine("The original string, without \"foo\" is now:\n '{0}'", newOriginal);
 

 
</string></string>

GeneralRe: You don't need to write this. The framework has most of these features already.mvpJohn Simmons / outlaw programmer7 Nov '08 - 11:12 
Yes, I knew about the string.Split() function before I did this. Notable differences between string.Split() and this class is that this class allows delimiter *strings*, quoted delimited strings, and it allows you to add/delete/insert new sub-strings within the original string.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: You don't need to write this. The framework has most of these features already.memberdave.dolan7 Nov '08 - 14:56 
so I guess you can argue that two calls are better, but, string split allows Chars or Strings, even Multiple Chars or Strings, as well as the intrinsic behavior modifier to create empty strings or ignore empty entires Smile | :) If you get your array of strings, which also happens to implement IEnumerable<String> then you can pass it as a constructor directly to a list which as you can see, actually does all your class does, including allowing you to add/remove/insert/delete/sort/reverse/indexof. One function call later, albeit on a different class (string) instead of list<string>, then you can slap them all back together. If you like to see it arranged the way you have it, that's fine, but you're really duplicating stuff that's already anticipated and implemented.
GeneralRe: You don't need to write this. The framework has most of these features already.mvpJohn Simmons / outlaw programmer7 Nov '08 - 16:02 
The beauty in having access to the source code is that you can mold it in your own image.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: You don't need to write this. The framework has most of these features already.mvpJohn Simmons / outlaw programmer20 Dec '08 - 23:22 
Your message caused me to go back and revisit the code. You are indeed correct that the Split function allows string delimiters, but it does not support quoted strings. Even so, I re-evaluated the Parse function and shortened it to just 25 lines of code.
 
As for the sorting, reversing, and ignoring of empty fields, that's not what this parser is all about. It's for strings that need to be parsed and processed in the original order of appearance, and missing fields are expected.
 
I'll be posting the new code sometime today.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: You don't need to write this. The framework has most of these features already.mvpJohn Simmons / outlaw programmer21 Dec '08 - 2:15 
Article updated, and new code posted.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: You don't need to write this. The framework has most of these features already.membertonyt23 Dec '08 - 18:56 
I think you're mistaken.
 
Quoted strings are not supported by string.Split.
 
Delimeters that appear within quoted substrings are not treated as delimiters.
GeneralRe: You don't need to write this. The framework has most of these features already.mvpJohn Simmons / outlaw programmer23 Dec '08 - 23:36 
His comment did cause a major re-write and resulting simplification of the class, and simplification is always a good thing.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralUpdate PostedmvpJohn Simmons / outlaw programmer31 Jul '07 - 2:33 
Base on comments received after I initially uploaded the article, I've made several sweeping changes. Note that the download filename has also changed.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralAn Update is ForthcomingmvpJohn Simmons / outlaw programmer30 Jul '07 - 2:11 
I'll be implementing a number of suggestions already posted.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralImprovementsmemberSteve Hansen30 Jul '07 - 1:20 
Since you're coming from C++ I just want to let you know a few things.
 
1- ArrayList is bad:
Since your project is in .NET 2.0 you should really use the generic List type ( System.Collections.Generic.List<T> )
This way you don't need to do ToString() or cast if you are using int/double etc
 
2- Hungarion Notation is bad:
Some people still use m_ for members (it's even used in .NET for fields) but forget the s/c/...
public string GetField(int nIndex)
use
public string GetField(int index)
instead
And get rid of the C prefix for classes, the only exception is I prefix for interfaces.
 
3- Destructor is bad:
Only use it if you need to clean up unmanaged resources, in this class it's totally unneeded, the garbage collector will clean up your class.
 
4- Enums:
Declare it outside and again, try to use the normal .NET notation:
public enum DeleteAction { DeleteAll, DeleteFirst, DeleteLast }
 
5- XML Comments:
Instead of:
//--------------------------------------------------------------------------------
// Re-parses the string
//--------------------------------------------------------------------------------
public int ResetOriginalString(string sVal, string sDelimiter, char cQuote)

use
/// <summary>
/// Re-parses the string.
/// </summary>
public int ResetOriginalString(string value, string delimiter, char quote)

 

But it's a nice helper class Smile | :)
Great article, got my 5
GeneralRe: ImprovementsmvpJohn Simmons / outlaw programmer30 Jul '07 - 1:43 
Steve Hansen wrote:
1- ArrayList is bad

 
I'll look into that tonight after work. I have a question - beyond the ToString() thing, what makes ArrayList "bad"?
 

Steve Hansen wrote:
2- Hungarion Notation is bad

 
I like it. It lets me know what type the variable is. This isn't technically "bad" as much as it is "personal preference".
 

Steve Hansen wrote:
3- Destructor is bad

 
It may be unnecessary, but I don't see it as "bad", but okay - I guess I'll get rid of it.
 

Steve Hansen wrote:
4- Enums:
Declare it outside

 
Outside of what? The namespace? The class? I tried outside the class and the compiler choked/puked on me. In C++, enums are typically defined in the class in which they're used.
 

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: ImprovementsmvpNishant Sivakumar30 Jul '07 - 1:56 
John Simmons / outlaw programmer wrote:
I have a question - beyond the ToString() thing, what makes ArrayList "bad"?

 
Any object added to it has to be upcast to Object. For value types, this mandates boxing which is an expensive process (compared to a cast). And for boxed objects, they then have to be unboxed during retrieval. Boxing, unboxing and all the casting that's involved results in poorer performance for large collections.
 
Also, there's no compile-time type checking possible since everything in an ArrayList is an Object.
 
John Simmons / outlaw programmer wrote:
Outside of what? The namespace? The class? I tried outside the class and the compiler choked/puked on me.

 
Enums are typically defined outside the class (within the namespace). What errors did you get?
 
John Simmons / outlaw programmer wrote:
It may be unnecessary, but I don't see it as "bad", but okay - I guess I'll get rid of it.

 
This destructor is actually not one - it's a finalizer. Any type with a finalizer will have a slight performance loss because during garbage collection types with finalizers are not immediately cleaned up, instead they are promoted to a finalization queue. And they are freed only during a later GC cycle. Thus any types with finalizers need at least 2 GC cycles to be freed. So in your case you are un-wantedly degrading the performance of the class by having a finalizer where one's not really needed.
 

John Simmons / outlaw programmer wrote:
I like it. It lets me know what type the variable is. This isn't technically "bad" as much as it is "personal preference".

 
Initially I thought like that too. But the tech architect at our place helped change my mind. When writing MFC code I now follow the MFC style naming, but when writing .NET code, I try and follow .NET naming conventions as far as possible - though I still accidentally mix them up on occasions Smile | :) In the long run you'll see that it's probably better to stick to .NET conventions for your managed assemblies.
 

GeneralRe: ImprovementsmvpJohn Simmons / outlaw programmer30 Jul '07 - 2:54 
Nishant Sivakumar wrote:
Initially I thought like that too. But the tech architect at our place helped change my mind. When writing MFC code I now follow the MFC style naming, but when writing .NET code, I try and follow .NET naming conventions as far as possible - though I still accidentally mix them up on occasions In the long run you'll see that it's probably better to stick to .NET conventions for your managed assemblies.

 
You haven't convinced me. I still prefer hungarian notation because it actually serves a purpose. I'll google it and see if I can find a tangible reason not to use it.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: ImprovementsmemberTodd Smith30 Jul '07 - 6:14 
Intellisense will provide you with the info you get from hungarian notation. We didn't have those in the past.
 
Hungarian came from the world of C. MS decided to use it in C++ land (doh).
 
The three biggest gripes are:
 
1) it adds uneeded noise
2) you now have a type integrated into your variable name, which if you decide to change you will also need to update all references
3) it only make sense for some basic types (int, string, editbox, etc.) but you'll find in C# they only make up for a small percentage of your object types. What do you do for the rest of the types? I think this is where you eventually let go of the hungarian notation.
 
btw here's a few coding styles for .NET
 
http://www.idesign.net/idesign/download/IDesign%20CSharp%20Coding%20Standard.zip[^]
http://www.icsharpcode.net/TechNotes/SharpDevelopCodingStyle03.pdf[^]
http://www.tiobe.com/standards/gemrcsharpcs.pdf[^]
 
Todd Smith

GeneralRe: ImprovementsmvpJohn Simmons / outlaw programmer31 Jul '07 - 5:05 
Todd Smith wrote:
1) it adds uneeded noise

 
Opinion.
 

Todd Smith wrote:
2) you now have a type integrated into your variable name, which if you decide to change you will also need to update all references

 
Search.Replace (all files if necessary)
 
Todd Smith wrote:
3) it only make sense for some basic types (int, string, editbox, etc.) but you'll find in C# they only make up for a small percentage of your object types.

 
I've already said that. I only use it for intrinsic types.
 
Todd Smith wrote:
btw here's a few coding styles for .NET

 
Blah, blah, blah. Smile | :)

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Improvementsmemberelektrowolf7 Nov '08 - 10:17 
John Simmons / outlaw programmer wrote:
Todd Smith wrote:
3) it only make sense for some basic types (int, string, editbox, etc.) but you'll find in C# they only make up for a small percentage of your object types.
 

I've already said that. I only use it for intrinsic types.

 
And for those it should be clear of which type they are by just reading the var name, without a prefix. Otherwise, in modern IDEs like vs you can just hover the variable and you see its type.
GeneralRe: ImprovementsmvpJohn Simmons / outlaw programmer7 Nov '08 - 11:15 
elektrowolf wrote:
Otherwise, in modern IDEs like vs you can just hover the variable and you see its type.

 
Man, this is an OLD argument (not only did I concede the point, for the .Net purists, I now use naming conventions they expect). I still stand by my claim that you cannot assume that everyone will be using an IDE with some form of intellisense.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Improvementsmemberlpt21 Dec '08 - 5:46 
Hungarian notation can provide helpful information. If you come across a line of code like this...
err = fn();
From the variable name you can assume that err is some type of error information, but you need to either read through the code or use an IDE feature to track down what err is.
sErr = fn();
iErr = fn();
Is a vast improvement because it lets you know that the error information returned is a string or an integer error code.
 
My preference is to avoid Hungarian notation but incorporate such clues in the variable name e.g.
errMsg = fn();
errID = fn();

GeneralRe: ImprovementsmemberSteve Hansen30 Jul '07 - 2:03 
1- For string it doesn't matter as much (it's only a method call extra for ToString()) but for value types it safes you from boxing/unboxing (placing value types on the heap) which does costs a lot.
 
2- All the Microsoft .NET coding guide lines recommend against it, was just letting you know.
 
3- The "bad" thing about it is that your object is handled differently by the garbage collector because you defined a destructor.
 
4- Outside of the class
 
public namespace MyNamespace
{
public enum MyEnum { Value1, Value2, Value3 }
public class MyClass
{
public void TestMethod(MyEnum value)
{}
}
}

 
The big difference with enums in C# is that the values can have the same name.
enum Enum1 { Value1, Value2 }
enum Enum2 { Value2, Value3 }

 
Is perfectly legal and there is no confusion between Enum1.Value2 and Enum2.Value2, which iirc was a problem in C++.
 
For the record, I'm not criticizing you, just pointing out some differences between working with C++ and C#
GeneralRe: ImprovementsmvpJohn Simmons / outlaw programmer30 Jul '07 - 2:09 
Steve Hansen wrote:
For the record, I'm not criticizing you, just pointing out some differences between working with C++ and C#

 
Yeah, I know. I was just asking the expected "why's".
 


 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

AnswerRe: Improvementsmembertorial30 Jul '07 - 3:19 
Regarding Hungarian Notation -- Joel Spolsky makes a good point that Hungarian Notation isn't bad, but has been misused : http://www.joelonsoftware.com/articles/Wrong.html

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 21 Dec 2008
Article Copyright 2007 by John Simmons / outlaw programmer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid