1

I'm attempting to create a method which checks whether a String contains any Strings contained within an IEnumerable<String>.My method so far is this:

public static Boolean ContainsAny(this String Self, IEnumerable<String> Fragments, StringComparer CompareType = StringComparer.CurrentCulture)
{
    foreach (var fragment in Fragments)
    {
        if (Self.Contains(fragment,CompareType))
        {
            return true;
        }
    }
    return false;
}

However, this won't compile because StringComparer.CurrentCulture ins't a compile time constant as shown by this error:

> Error 1   Default parameter value for 'CompareType' must be a
> compile-time constant

My question is, what is an acceptable default value which I can use for CompareType which will result in the same behavior as if it were possible to have it default to StringComparer.CurrentCulture?

HennyH
  • 7,794
  • 2
  • 29
  • 39

2 Answers2

3

A common trick to deal with non-compile-time constants is moving the check to runtime, like this:

public static Boolean ContainsAny(
    this String self
,   IEnumerable<String> fragments
,   StringComparer comparerArg = null)
{
    var comparer = comparerArg ?? StringComparer.CurrentCulture;
    ...
}

You make null the default in the method signature, and then the first thing you check is if the value passed is null, in which case you substitute it with StringComparer.CurrentCulture. Note that in order for this trick to work, null must not be a valid parameter that one would reasonably want to pass to your method, and your documentation should say that passing null is equivalent to passing StringComparer.CurrentCulture.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I learnt something new from your answer -- the `??` operator, I would have normally used a ` _ ? X : Y`, thanks for the answer! – HennyH May 16 '13 at 10:11
  • @HennyH they are called [null-coalescing](http://msdn.microsoft.com/en-us/library/ms173224.aspx) operator. Pretty much a standard thing across languages. They return the second argument if first is null, otherwise the first. See this question for instance http://stackoverflow.com/questions/278703/unique-ways-to-use-the-null-coalescing-operator – nawfal May 16 '13 at 10:20
2

The simplest, cleanest, and consistent (with framework) is to have overloads:

public static Boolean ContainsAny(this String Self, IEnumerable<String> Fragments)
{
    returns ContainsAny(Self, Fragments, StringComparer.CurrentCulture);
}

public static Boolean ContainsAny(this String Self, IEnumerable<String> Fragments, StringComparer CompareType)
{
    foreach (var fragment in Fragments)
    {
        if (Self.Contains(fragment,CompareType))
        {
            return true;
        }
    }
    return false;
}

If you do want only one overload, then may be:

public static Boolean ContainsAny(this String Self, IEnumerable<String> Fragments, StringComparer CompareType = null)
{
    if (CompareType == null)
        ComapreType = StringComparer.CurrentCulture;

    foreach (var fragment in Fragments)
    {
        if (Self.Contains(fragment,CompareType))
        {
            return true;
        }
    }
    return false;
}

Suggestions:

  1. Use language aliases like bool instead of Boolean. Its recommended and makes code short.

  2. In C# parameter names starts with lower case (camelCase)

  3. If you have Linq, the code is as sweet as:

    return Fragments.Any(x => self.Contains(x, compareType));
    
nawfal
  • 70,104
  • 56
  • 326
  • 368
  • Thanks, I like the first approach's method of dealing with the problem, especially as I don't need to implement it with only one method. – HennyH May 16 '13 at 10:08
  • Part of the reason why overloads are "consistent with frameworks" is that default arguments are relatively new to the C# language. Prior to them, all frameworks used overloads, so they kept them after the introduction of default parameters for backward compatibility. – Sergey Kalinichenko May 16 '13 at 10:12
  • @dasblinkenlight I agree, so plus 1 to you.. :) Personally I like and use optional parameters! The only thing I hate about it is to see `[....]` brackets in intellisense! :) – nawfal May 16 '13 at 10:14