Reputation: 7438
I have to check one variable if it contains a value from a list of strings, for e.g.:
status == "Open" || status =="Active" || status =="Reopen" || status = "Inactive" etc..
In SQL it is very easy to write this kind of statement, e.g.:
select * from ticket where status in ("Open","Active","Reopen","Inactive")
I wonder whether we don't have such easy statement in C#?
Do anybody know any easy way like SQL to write this kind of statements without using generic types of if else, foreach loop, or LINQ, etc.
I know LINQ is there, but still it is not as simple as the in
feature of SQL.
Upvotes: 5
Views: 3907
Reputation: 559
Its possible to create an extension method that can handle this as mentioned earlier...
Add the necessary imports
using System;
using System.Linq; // required if using .Contains() or .Any()
using System.Collections.Generic;
Create an Extension class. The following gives three options for the extension method.
public static class Extensions
{
public static bool InV1(this string input, string[] collection)
{
if (collection == null || collection.Length == 0)
{
throw new ArgumentException("Parameters empty");
}
for (int i = 0; i < collection.Length; i++)
{
if (input.Equals(collection[i]))
{
return true;
}
}
return false;
}
public static bool InV2(this string input, string[] collection)
{
if (collection == null || collection.Length == 0)
{
throw new ArgumentException("Parameters empty");
}
if (collection.Contains(input))
{
return true;
}
return false;
}
// Credit: https://stackoverflow.com/a/3165188/1165173
public static bool InV3<T>(this T input, params T[] items)
{
if (input == null)
{
throw new ArgumentException("Input is empty");
}
if (items == null || items.Length == 0)
{
throw new ArgumentException("Parameters empty");
}
return items.Any(i => i.Equals(input)); // Any() function exists immediately on first item
}
}
Invoke the extension method within your business logic.
public class Program
{
public static void Main()
{
var input = "test1";
var collection = new [] { "test1", "test2", "test3", "test4", "test5" };
// using contains
var result1 = input.InV1(collection);
Console.WriteLine(result1);
// using iteration
var result2 = input.InV2(collection);
Console.WriteLine(result2);
// using linq
var result3 = input.InV3("test1", "test2", "test3", "test4", "test5");
Console.WriteLine(result3);
// recursively
var salesIds = new List<int>() { 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239 };
foreach (var id in salesIds)
{
if (id.InV3(1230, 1238, 1239))
{
Console.WriteLine("exists: " + id);
}
}
}
}
UPDATE: .NET 9 preview makes this even easier, you can use the following...
using System;
using System.Buffers;
public class Program
{
// Credit: Nick Chapsas - 25/03/2024
// https://www.youtube.com/watch?v=q0VENoIXWso
public static void Main()
{
SearchValues<string> searchValues = SearchValues.Create(["Test A", "Test B"], StringComparison.OrdinalIgnoreCase);
Console.WriteLine(searchValues.Contains("Test B"));
// or another way
Console.WriteLine(MemoryExtensions.ContainsAny("Test A", searchValues));
}
}
Upvotes: -1
Reputation: 7438
This works for me.
(new List<string>{ "Open", "Active", "Reopen", "InActive" }).Contains("status");
I also like the c# 3.0 feature of creating extension to String class
public static class StringExtensions
{
public static bool In(this string @this, params string[] strings)
{
return strings.Contains(@this);
}
}
and later we can use it in Simplest way
status.Contains("Open", "Active", "Reopen", "InActive");
This is great if you have to write many statements like this I prefer to write this extension for if I am writing old style for atleast 5-10 statement statement in 2 or more files.
Upvotes: 1
Reputation: 14522
tickets.Where(t => new[] {"Open",
"Active",
"Reopen",
"InActive"}.Any(x => x == t.status))
You can also use the Contain method instead of the Any method, but use the Any method if there's any comparement logic you would like to implement, instead of the default equality comparer.
OR
Implement extensions to support IN method:
public static class Extensions
{
public static bool In<TItem>(this TItem source, Func<TItem, TItem, bool> comparer, IEnumerable<TItem> items)
{
return items.Any(item => comparer(source, item));
}
public static bool In<TItem, T>(this TItem source, Func<TItem, T> selector, IEnumerable<TItem> items)
{
return items.Select(selector).Contains(selector(source));
}
public static bool In<T>(this T source, IEnumerable<T> items)
{
return items.Contains(source);
}
public static bool In<TItem>(this TItem source, Func<TItem, TItem, bool> comparer, params TItem[] items)
{
return source.In(comparer, (IEnumerable<TItem>)items);
}
public static bool In<TItem, T>(this TItem source, Func<TItem, T> selector, params TItem[] items)
{
return source.In(selector, (IEnumerable<TItem>)items);
}
public static bool In<T>(this T source, params T[] items)
{
return source.In((IEnumerable<T>)items);
}
}
And use like this:
bool b;
b = 7.In(3, 5, 6, 7, 8); // true
b = "hi".In("", "10", "hi", "Hello"); // true
b = "hi".In("", "10", "Hi", "Hello"); // false
b = "hi".In((s1, s2) => string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase), "", "10", "Hi"); // true
var tuples = new List<Tuple<int, string>>();
for (var i = 0; i < 10; i++)
{
tuples.Add(Tuple.Create(i, ""));
}
var tuple = Tuple.Create(3, "");
b = tuple.In(tup => tup.Item1, tuples); // true
Upvotes: 12
Reputation: 720
(new [] { "Open", "Active", "Reopen", "InActive" }).Contains(status)
Upvotes: 9