Peter Petrov’s Weblog

var me = from practice in programming where practice.IsBestPractice && practice.UseLambda select practice.OptimalPerformance;

Useful method – 8 of N – String Capitalize First (ToTitleCase) June 30, 2008

I’ve wanted to rename a lots of files. I’ve also wanted the name of the files to follow my convention to capitalize every first letter. I couldn’t find such functionality in the string class. I’ve googled and I’ve found the TextInfo class and ToTitleCase method. It gets the job done and perfectly suits me needs.

Here’s how we can use it

TextInfo ti = Thread.CurrentThread.CurrentCulture.TextInfo;
string name = "petar petrov - XML developer";
string properName = ti.ToTitleCase(name);
// properName = "Petar Petrov - XML Developer"

Note that the XML isn’t transformed to Xml which is the correct behavior for me.

Advertisements
 

Useful method – 7 of N – Ignore case on String.Replace() June 27, 2008

Filed under: .NET Framework,C# — ppetrov @ 3:51 pm
Tags: , , ,

I’ve posted a method to determine if a string contains another string ignoring the case. I’ve also looked all string methods and I’ve found Replace isn’t available in a ignore case variant. I’ve created the missing overload(using an extension methods).

public static string Replace(this string original, string oldValue, string newValue, StringComparison comparisionType)
 {
 if (oldValue == null)
 throw new ArgumentNullException("oldValue");
 if (newValue == null)
 throw new ArgumentNullException("newValue");

 var result = original;

 if (oldValue != newValue)
 {
 int index = -1;
 int lastIndex = 0;

 var buffer = new StringBuilder();

 while ((index = original.IndexOf(oldValue, index + 1, comparisionType)) >= 0)
 {
 buffer.Append(original, lastIndex, index - lastIndex);
 buffer.Append(newValue);

 lastIndex = index + oldValue.Length;
 }
 buffer.Append(original, lastIndex, original.Length - lastIndex);

 result = buffer.ToString();
 }
 return result;
 }

UPDATE : I’ve updated the method to allow newValue to be string.Empty. It will perform like a remove method. WordPress source code posting is broken 😦

 

Useful method – 6 of N – Ignore case on String.Contains()

Filed under: .NET Framework,C# — ppetrov @ 12:39 pm
Tags: , , ,

The easiest way to see if a String contains another string is to use the method Contains().

The documentation has Remarks

This method performs an ordinal (case-sensitive and culture-insensitive) comparison. The search begins at the first character position of this string and continues through the last character position.

But what if we want a case-insensitive comparison? The answer is simple – we can use IndexOf(). The problem is the name of the method isn’t as intuitive as Contains() is(Contains calls IndexOf under the hood). To create a little comfort I’ve wrapped the IndexOf() call to an extension method which will determine if a string contains another string ignoring the case.

public static bool Contains(this string original, string value, StringComparison comparisionType)
{
    return original.IndexOf(value, comparisionType) >= 0;
}

In fact we pass StringComparison as parameter so it’s easy to specify the culture and the case.

 

Don’t use .ToUpper() or .ToLower()

Filed under: .NET Framework,C# — ppetrov @ 11:36 am
Tags: , , ,

I’ve seen on many code snippets and posts an inadequate use of ToUpper() and ToLower() methods of the string class. It’s a well know fact that string is immutable and these methods will return a copy of the original string.

A String object is called immutable (read-only) because its value cannot be modified once it has been created. Methods that appear to modify a String object actually return a new String object that contains the modification.

If you need to compare two strings ignoring the case, we must use the static method Equals()


string.Equals("abc", "ABC", StringComparison.OrdinalIgnoreCase)

or the instance one.


"abc".Equals("ABC", StringComparison.OrdinalIgnoreCase)

StartsWith(), EndsWith(), IndexOf() etc – all of these methods provide a way to specify the
StringComparison type.
An interesting method is Contains(). There’s no way to specify the StringComparison type or to say ignoreCase = true.
Actually it’s an alias for IndexOf(). In Reflector we can see the following implementation

public bool Contains(string value)
{
    return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

To fill this gap I’ve decided to write an extension method with an additional parameter

        public static bool Contains(this string original, string value, StringComparison comparisionType)
        {
            return original.IndexOf(value, comparisionType) >= 0;
        }

Now we can use it like this

"abc".Contains("AB", StringComparison.OrdinalIgnoreCase)

I think it’s a useful method so I’ll post this extension method as a separate post.

 

Useful method – 5 of N – Format/Beautify XML June 24, 2008

Filed under: C#,XML — ppetrov @ 7:27 pm
Tags: , , ,

Here’s a method to format a XML string or a XML file.

    public static string Format(string xmlContents)
    {
        StringBuilder buffer = new StringBuilder();

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xmlContents);

        using (var writer = XmlTextWriter.Create(buffer, new XmlWriterSettings() { Indent = true }))
        {
            doc.Save(writer);
        }

        return buffer.ToString();
    }

    public static void FormatFile(string inputFile)
    {
        FormatFile(inputFile, inputFile);
    }

    public static void FormatFile(string inputFile, string outputFile)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(inputFile);

        using (var writer = XmlTextWriter.Create(outputFile, new XmlWriterSettings() { Indent = true }))
        {
            doc.Save(writer);
        }
    }

I’ve tried to optimize these methods by replacing the XmlDocument with XPathDocument. The documentation of XPathDocument says:

Provides a fast, read-only, in-memory representation of an XML document using the XPath data model.

My first thought was that the read-only nature of XPathDocument will speed up my code, so I end up with this method.

    public static string FormatUsingXPath(string xmlContents)
    {
        StringBuilder buffer = new StringBuilder();

        using (var writer = XmlTextWriter.Create(buffer, new XmlWriterSettings() { Indent = true }))
        {
            using (XmlTextReader reader = new XmlTextReader(xmlContents, XmlNodeType.Document, null))
            {
                XPathDocument doc = new XPathDocument(reader);
                writer.WriteNode(doc.CreateNavigator(), false);
            }
        }

        return buffer.ToString();
    }

Unfortunately the XPath version is 10% slower. I think the difference comes from the creation of the XmlTextReader.

If we apply the method on the following unformatted XML


<?xml version="1.0"?>
<catalog>
 <book id="bk101">
 <author>Gambardella, Matthew</author><title>XML Developer's Guide</title>

 <genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
 <description>An in-depth look at creating applications
 with XML.</description>

 </book>
</catalog>

we will receive a well formatted version of our input XML.

Unfortunately there’s a problem with wordpress.com XML formatting and the well formatted XML isn’t shown as expected.

 

Useful method – 4 of N – String Aggregation

Filed under: C# — ppetrov @ 1:23 pm
Tags: ,

I’ve read a blog post on extension methods. There is a method on String Aggregation but I didn’t like its implementation. A few months back, I have coded the same method. Here’s my version

        public static string Aggregate<T>(this IEnumerable<T> values)
        {
            return Aggregate(values, ",");
        }

        public static string Aggregate<T>(this IEnumerable<T> values, string separator)
        {
            return values.Aggregate(x => x.ToString(), separator);
        }

        public static string Aggregate<T>(this IEnumerable<T> values, Func<T, string> toString)
        {
            return values.Aggregate(toString, ",");
        }

        public static string Aggregate<T>(this IEnumerable<T> values, Func<T, string> toString, string separator)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (toString == null)
            {
                throw new ArgumentNullException("toString");
            }

            StringBuilder buffer = new StringBuilder();

            foreach (var v in values)
            {
                if (buffer.Length > 0)
                {
                    buffer.Append(separator);
                }
                buffer.Append(toString(v));
            }

            return buffer.ToString();
        }

This version is 10 times faster and it uses less memory. The method in the post creates many temporary strings, so it consumes a lot of memory. Probably we can speed up my implementation by removing the check

if (buffer.Length > 0) { //... }

and removing the separator from the start but I don’t like the idea because it will create a copy of the resulting (big) string.

 

Object Initializers – Thread safety June 19, 2008

Filed under: C# — ppetrov @ 6:09 pm
Tags: , ,

One of the new features in C# 3.0 is object initializers. They greatly simplify the creation of new objects.

In C# 2.0 we have to say:

Person p = new Person();
p.Name = "Petar Petrov";
p.Age = 25;

Now in C# 3.0 we have

Person p = new Person() {Name = "Petar Petrov", Age = 25};

It’s simple and easy to use.
However there is one subtle difference between these two snippets.
In multithreaded environment if we use the first version of the code it’s possible to have partially initialized Person object, if the thread is interrupted between the Person’s constructor and setting the name or the age of the Person. In this case we will end up with a Person with no Age.

If we use the object initializers this situation isn’t possible. For the C# 3.0 version of the snippet the compiler generates the following code


Person p = null;
Person __p = new Person();
__p.Name = "Petar Petrov";
__p.Age = 25;
p = __p;

It’s obvious that whenever the thread is interrupted we can’t end up with partially initialized Person. The two possible options are :

p = null;

or

p = __p;

where __p is fully initialized Person.