6

Somewhere in the back of my head a tiny voice is telling me "the C# code below smells".

private const string STR_ConnectionString = "ConnectionString";
private readonly string upperCaseConnectionString = STR_ConnectionString.ToUpperInvariant();
// a lot further on
string keyAttributeValue = keyAttribute.Value;
if (keyAttributeValue.ToUpperInvariant().StartsWith(upperCaseConnectionString)) 
{
    // some C# code handling a key that starts with "ConnectionString"
}

The constant STR_ConnectionString is used in other places in the code as well.

How to get rid of the smell?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Jeroen Wiert Pluimers
  • 23,965
  • 9
  • 74
  • 154

5 Answers5

5

You can use the overloaded StartsWith method taking a StringComparison enum value:

keyAttributeValue.StartsWith(STR_ConnectionString, StringComparison.OrdinalIgnoreCase) // or use StringComparison.InvariantCultureIgnoreCase here
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
4

There is a StartsWith overload which supports case-insensitive matching:

if (keyAttributeValue.StartsWith(STR_ConnectionString, 
                                 StringComparison.InvariantCultureIgnoreCase)
{
    ...
}

It also makes your code more readable, because it expresses your intention: What you really want is a case-insensitive comparison, and that's what's written here. You don't really want "a case-sensitive comparison of values converted to upper-case"... that's just the workaround you use to achieve the goal.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
2

If it smells bad because you're doing the ToUpper then the string compare, those can be combined using an overload of startswith:

STR_ConnectionString..StartsWith(upperCaseConnectionString, StringComparison.CurrentCultureIgnoreCase);

However, it looks like you're rolling your own way to handle application configuration, which you shouldn't do. See http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx

Arbiter
  • 984
  • 1
  • 10
  • 24
  • It's sort of an app configuration, but not quite, that I inherited from some teams that should have had a kick in the butt years ago :) You don't want to know how the rest of the inherited code looks like. Well maybe you do, but not all at once. Rest assured I'm going to do major refactoring work the upcoming months, step by step. – Jeroen Wiert Pluimers Jan 09 '12 at 15:30
2

There's always

keyAttributeValue.StartsWith(STR_ConnectionString, StringComparison.InvariantCultureIgnoreCase)

but that will not perform as well as what you have. If you need to do it thousands of times per second, stick with what you have. If not, just do a case-insensitive match.

Also consider

keyAttributeValue.StartsWith(STR_ConnectionString, StringComparison.OrdinalIgnoreCase)

which is faster and is probably what you want anyway.

Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
Gabe
  • 84,912
  • 12
  • 139
  • 238
1

I've made an extension method that uses StringComparison to ignore case to deal with this in my projects.

public static string StartsWithIgnoreCase(this string value, string startsWith)
{
    return value.StartsWith(value, StringComparison.InvariantCultureIgnoreCase);
}

You can add null checks if you wish.

cadrell0
  • 17,109
  • 5
  • 51
  • 69
  • -1 Your extension method is just hiding which type of IgnoreCase you are using. Check http://stackoverflow.com/a/417992/146513 and http://blogs.msdn.com/b/noahc/archive/2007/06/29/string-equals-performance-comparison.aspx to know the difference and take that into account in each specific case. – Mariano Desanze Oct 17 '13 at 14:59
  • @Protron I used `InvariantCulture` because OP used `ToUpperInvariant`. You should always use the correct culture. Thanks for the good links. – cadrell0 Oct 17 '13 at 15:04
  • @cadrell0 I should have said that I think your answer is perfectly correct (for this particular case) if you take it outside the extension method. But I think is *dangerous* to put it in an extension method because many people will reuse that without knowing which culture are using. So I prefer to use the StartsWith the framework provides without extensions. – Mariano Desanze Oct 17 '13 at 18:40