[C#.NET] 擴充方法 - 為 IEnumerable<T> 擴充查詢欄位方法
集合有個 Contains 方法可判斷集合內有沒有該物件,用法如下
if (intList.Contains(5))
Console.WriteLine("Exist");
else
Console.WriteLine("No Exist");
但集合內存放的是一個類別時,原本的 Contains 就不敷使用。
假設我有個類別
{
public string Name { get; set; }
public int Age { get; set; }
}
在集合裡面裝了這些東西
list.Add(new Customer() { Name = "jordan", Age = 19 });
list.Add(new Customer() { Name = "小章", Age = 20 });
list.Add(new Customer() { Name = "盧克", Age = 34 });
list.Add(new Customer() { Name = "9gy", Age = 29 });
list.Add(new Customer() { Name = "小盧克", Age = 17 });
假設我要查詢某個欄位是否存在,以往我都會這麼寫
where data.Name == "小章"
select data;
int count = query.Count();
if (count > 0)
{
Console.WriteLine("Exist");
}
else
{
Console.WriteLine("No Exist");
}
lambda寫法
if (count > 0)
{
Console.WriteLine("Exist");
}
else
{
Console.WriteLine("No Exist");
}
用迴圈也可以
{
if (item.Name=="小章")
{
Console.WriteLine("Exist");
return;
}
}
Console.WriteLine("No Exist");
這樣的東西不斷的出現在專案裡也挺累人的,不如就為它寫個擴充方法,相關寫法請參考[C#.NET] C# 3.0 (VS 2008) 語言新特性,下列方法主要是利用反射進行欄位查詢,
1.IsContains:回傳查詢欄位是否存在
2.Contains:回傳查詢欄位的值
3.IndexOf:回傳查詢欄位的索引值
using System.Linq;
using System.Reflection;
namespace System.Servconn.Extensions
{
public static partial class ExtendSyntax
{
public static bool IsContains<T>(this IEnumerable<T> List, string PropertyName, object Value)
{
object Exist = null; bool IsExist = false; int Position = -1;
contains<T>(List, PropertyName, Value, ref Exist, ref IsExist, ref Position);
return IsExist;
}
public static T Contains<T>(this IEnumerable<T> list, string PropertyName, object Value)
{
object Exist = null; bool IsExist = false; int Position = -1;
contains<T>(list, PropertyName, Value, ref Exist, ref IsExist, ref Position);
if (Exist != null)
{
return (T)Exist;
}
else
{
return default(T);
}
}
public static int IndexOf<T>(this IEnumerable<T> List, string PropertyName, object Value)
{
object Exist = null; bool IsExist = false; int Position = -1;
contains<T>(List, PropertyName, Value, ref Exist, ref IsExist, ref Position);
return Position;
}
private static void contains<T>(this IEnumerable<T> List, string PropertyName, object Value, ref object Exist, ref bool IsExist, ref int Position)
{
if (List == null)
{
throw new ArgumentNullException("List");
}
if (string.IsNullOrEmpty(PropertyName))
{
throw new ArgumentNullException("PropertyName");
}
if (Value == null)
{
throw new ArgumentNullException("Value");
}
Type type = typeof(T);
PropertyInfo propertyInfo = type.GetProperty(PropertyName);
if (propertyInfo == null)
{
throw new NotSupportedException(PropertyName);
}
var query = from data in List
where propertyInfo.GetValue(data, null).Equals(Value)
let Index = List.IndexOf(data)
select new { Index, data };
if (query.Count() > 0)
{
IsExist = true;
Exist = query.First().data;
Position = query.First().Index;
}
}
}
}
如此一來便可為List<T>增加上述屬性,正確來說凡是有繼承IEnumerable<T>的類別,都可以享用上面的方法。
補充:
經91哥提醒,
Any 方法 可以判斷欄位是否存在
ElementAt<TSource>可以依索引值取得相關的值
白寫了(攤手)
查詢索引值的部份用了牛刀殺雞浪費了效能(反射),91哥也建議使用delegate做掉,於是我改成
{
if (List == null)
{
throw new ArgumentNullException("list");
}
if (Condition == null)
{
throw new ArgumentNullException("predicate");
}
int index = 0;
foreach (var item in List)
{
if (Condition(item))
{
return index;
}
index++;
}
return -1;
}
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET