1

I want to test whether a certain string is contained in a short list of strings. Currently the code is like this:

if (new List<string> { "A", "B", "C" }.Contains (str)) {

However, this seems bloated. For instance, iirc, in Java I could simply write {"A", "B", "C"}.Contains(str) which would be much preferable to the above.

I'm sure there is a better way in C#. Could you point it out?

mafu
  • 31,798
  • 42
  • 154
  • 247

5 Answers5

6

I guess you could shorten it down to:

if ((new []{ "A", "B", "C" }).Contains (str)) {

Don't know how much of an actual difference it would make though.

Update: if you know that you will be testing for exactly one letter, I see no reason to make a list or array of it:

if ("ABC".Contains(str)) {

That code is both shorter and faster. But then again I guess that the single-letter strings were merely samples...

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • That's already a big improvement. I guess it is a bit faster as well. – mafu Aug 27 '09 at 08:11
  • @mafutrct: I did a performance test and it seems as if my solution is actually slower. So right now it's a choice between shorter or faster code ;o) – Fredrik Mörk Aug 27 '09 at 08:17
  • Luckily right now I actually need to test for single characters only. How could I possibly miss "ABC".Contains?! – mafu Aug 27 '09 at 09:17
6

You could write an extension method:

public static bool In<T>(this T obj, params T[] candidates)
{
    return obj.In((IEnumerable<T>)candidates);
}

public static bool In<T>(this T obj, IEnumerable<T> candidates)
{
    if(obj == null) throw new ArgumentNullException("obj");
    return (candidates ?? Enumerable.Empty<T>()).Contains(obj);
}

Which you could then use to do:

if(str.In("A", "B", "C")) { ... }
Lee
  • 142,018
  • 20
  • 234
  • 287
  • An interesting approach. Right now I like Fredrik's second solution better, but I will keep your idea in mind. +1 – mafu Aug 27 '09 at 09:16
  • Decided to accept this answer anyway, as it is more universal. – mafu Sep 07 '09 at 11:12
2

What about this approach:

"A;B;C".Split(';').Contains(str);
Christian
  • 4,261
  • 22
  • 24
2

If your short list of strings are constant, you should use a static readonly string array.

The benefit is it's easy to write and it does not instantiate new List every time you need to perform the check.

private static readonly string[] Names = new string[] { "A", "B", "C" };

...

if (Names.Contains(str)) {

However, this solution is not scalable as the search is done in a linear fashion. Alternatively, you can define your constant array in a sorted manner and use BinarySearch over the array.

// this has to be sorted
private static readonly string[] Names = new string[] { "A", "B", "C" };

...

if (Array.BinarySearch(Names, str) >= 0) {
Fnop
  • 226
  • 1
  • 5
  • From a performance POV, I like your solution. However, my main concern was code length. – mafu Aug 27 '09 at 09:12
2

To completely change it up:

switch(str){
    case "A":
    case "B":
    case "C":
       contains = true;
       break;

    default:
       contains = false;
       break;
}
Noon Silk
  • 54,084
  • 6
  • 88
  • 105