c# where

2019-03-04 14:28:27 qq_40091720 阅读数 1063

https://blog.csdn.net/zj735539703/article/details/46506575
一、Where 扩展的不足

如下界面,可通过姓名、编号和地址对人员进行模糊查询:

这里写图片描述

我们通常会写出如下代码:

public IQueryable<Person> Query(IQueryable<Person> source, string name, string code, string address)
{
    var result = source;
    if(string.IsNullOrEmpty(name) == false)
        result = source.Where(p => p.Name.Contains(name));
    if (string.IsNullOrEmpty(code) == false)
        result = source.Where(p => p.Code.Contains(code));
    if (string.IsNullOrEmpty(address) == false)
        result = source.Where(p => p.Code.Contains(address));
    return result;

以上代码有大量的 if 显得很繁琐,代码可读性不好。

二、创建并使用 WhereIf 扩展

WhereIf 扩展比较简单,代码如下:

public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
{
    return condition ? source.Where(predicate) : source;
}

上面的代码可简化成:

public IQueryable<Person> Query(IQueryable<Person> source, string name, string code, string address)
{
    return source
        .WhereIf(p => p.Name.Contains(name), string.IsNullOrEmpty(name) == false)
        .WhereIf(p => p.Code.Contains(code), string.IsNullOrEmpty(code) == false)
        .WhereIf(p => p.Code.Contains(address), string.IsNullOrEmpty(address) == false);
}

是不是更易读一些!

当然,我们还需要一个 IEnumerable<T> 版本的 WhereIf 扩展,方便对集合进行查询:

public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
{
    return condition ? source.Where(predicate) : source;
}

三、WhereIf 完整代码

namespace System.Linq
{
    public static class WhereIfExtension
    {
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, int, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, int, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
    }
}

将类放入 System.Linq 命名空间中,随时使用,更方便。

2019-08-01 23:38:00 weixin_30478923 阅读数 360
原文:c# where(泛型类型约束)

定义:在定义泛型的时候,我们可以使用 where 限制参数的范围。

使用:在使用泛型的时候,你必须尊守 where 限制参数的范围,否则编译不会通过。

 

六种类型的约束:

T:类(类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。)

    class MyClass<T, U>
        where T : class///约束T参数必须为“引用 类型{ }”
        where U : struct///约束U参数必须为“值 类型”
    { }

T:结构(类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。)

    class MyClass<T, U>
        where T : class///约束T参数必须为“引用 类型{ }”
        where U : struct///约束U参数必须为“值 类型”
    { }

T:new()(类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。)

class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
    // ...
}

T:<基类名>(类型参数必须是指定的基类或派生自指定的基类。)

public class Employee{}

public class GenericList<T> where T : Employee

T:<接口名称>(类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。)

复制代码
    /// <summary>
    /// 接口
    /// </summary>
    interface IMyInterface
    {
    }

    /// <summary>
    /// 定义的一个字典类型
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TVal"></typeparam>
    class Dictionary<TKey, TVal>
        where TKey : IComparable, IEnumerable
        where TVal : IMyInterface
    {
        public void Add(TKey key, TVal val)
        {
        }
    }
复制代码

T:U(为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。也就是说T和U的参数必须一样

class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}

 

一、可用于类:

public class MyGenericClass<T> where T:IComparable { }

二、可用于方法:

public bool MyMethod<T>(T t) where T : IMyInterface { }

三、可用于委托:

delegate T MyDelegate<T>() where T : new()
posted on 2019-08-01 23:38 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/11286115.html

2018-03-21 00:29:26 L_ZhiWei 阅读数 1312

首先贴出一段代码

public class BusinessBaseBLL<T, S> : BaseBLL<T, S> where T : new() where S : BusinessDAL<T>, new()

看到第一点感觉自己就蒙了,接触C#这么久,尽然怎么会用where,也不是很明白,今天查了一下msdn(点击打开链接),才明白,原来where是约束泛型的。

就像 

BaseBLL<T, S> where T : new() 

可以这样理解,T 必须是一个具有无参构造函数的类,其中new () 指的是无参构造函数约束;

我把第一理解为  BusinessBaseBLL<T, S> 类继承  BaseBLL<T, S> 

第二 BaseBLL<T, S> where T : new() T 的类型是无参构造的类

第三 BaseBLL<T, S> where S : BusinessDAL<T>, new()

S 是 BusinessDAL<T> 类型的,并且是具有无参构造函数的!


以上是本人的理解,如果有理解错误,请求大神批评指出,别误导他人!谢谢


2019-06-24 16:28:54 weixin_34302561 阅读数 299
C# where子句
 
where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量。
 1.接口约束。
 例如,可以声明一个泛型类 MyGenericClass,这样,类型参数 T 就可以实现 IComparable<T> 接口:

public class MyGenericClass<T> where T:IComparable { }

 2.基类约束:指出某个类型必须将指定的类作为基类(或者就是该类本身),才能用作该泛型类型的类型参数。
 这样的约束一经使用,就必须出现在该类型参数的所有其他约束之前。
class MyClassy<T, U>
 where T : class
 where U : struct
{
}

 3.where 子句还可以包括构造函数约束。
 可以使用 new 运算符创建类型参数的实例;但类型参数为此必须受构造函数约束 new() 的约束。new() 约束可以让编译器知道:提供的任何类型参数都必须具有可访问的无参数(或默认)构造函数。例如:
public class MyGenericClass <T> where T: IComparable, new()
{
 // The following line is not possible without new() constraint:

 T item = new T();
}
new() 约束出现在 where 子句的最后。

 4.对于多个类型参数,每个类型参数都使用一个 where 子句,
 例如:
interface MyI { }
class Dictionary<TKey,TVal>

where TKey: IComparable, IEnumerable
where TVal: MyI
{
 
public void Add(TKey key, TVal val)
 {
 }
}

5.还可以将约束附加到泛型方法的类型参数,例如:

public bool MyMethod<T>(T t) where T : IMyInterface { }

请注意,对于委托和方法两者来说,描述类型参数约束的语法是一样的:

delegate T MyDelegate<T>() where T : new()

 Link from : http://hi.baidu.com/%D0%A6%D3%F0%BA%A8%CC%EC/blog/item/9701871c28d2fb13413417fd.html

转载于:https://www.cnblogs.com/zhangchenliang/archive/2012/01/09/2316985.html

2017-07-19 15:43:46 sixdaycoder 阅读数 6730

where(泛型类型约束)

where关键词一个最重要的用法就是在泛型的声明、定义中做出约束。
约束又分为接口约束、基类约束、构造函数约束、函数方法的约束,我们慢慢介绍。

接口约束

顾名思义,泛型参数必须实现相应的接口才可以,看一个例子:

public interface IAccount {

        string Name {
            get;
        }

        decimal Balance {
            get;
        }
}


 public class Account : IAccount {
        private string name;
        public string Name {
            get {
                return name;
            }

        }

        private decimal balance;
        public decimal Balance {
            get {
                return balance;
            }
        }

        public Account(string name = "", decimal balance = 0) {
            this.name = name;
            this.balance = balance;
        }
   }


   public class MyClass<T> where T : IAccount {

        public MyClass() {
            Console.WriteLine("In MyClass<T> Ctor");    
        }

    }

public class MyClass<T> where T : IAccount中,where关键词指定了T必须实现IAcoount的接口才可以成功构造,例如:

namespace CSharp {
    class Program {
        static void Main(string[] args) {

            MyClass<Account> mc = new MyClass<Account>();
            //成功,Account实现了IAccount接口

            MyClass<string> m = new MyClass<string>();
            //构造失败,string没有实现IAccount接口,编译器提示错误
        }
    }
}

T也可以是泛型接口,例如MSDN给出的例子:

public class MyGenericClass<T> where T:IComparable { }  

基类约束

类型参数必须是指定的基类或派生自指定的基类,多用于继承体系之下,看个例子:

public class Account : IAccount {
        private string name;
        public string Name {
            get {
                return name;
            }

        }

        private decimal balance;
        public decimal Balance {
            get {
                return balance;
            }
        }

        public Account(string name = "", decimal balance = 0) {
            this.name = name;
            this.balance = balance;
        }
    }


    public class AccountDrived : Account {

        public AccountDrived(string name = "", decimal balance = 0):base(name, balance) {
            Console.WriteLine("In AccountDrived Ctor");
        }

    }
   //泛型参数只能是Account或者Account的派生类
    public class MyClass2<T> where T : Account {

        public MyClass2() {
            Console.WriteLine("In MyClass2<T> Ctor");
        }

    }

    class Program {
        static void Main(string[] args) {

            MyClass2<Account> a = new MyClass2<Account>();
            MyClass2<AccountDrived> b = new MyClass2<AccountDrived>();
            //MyClass2<string> c = new MyClass2<string>(); - error
        }
    }

构造函数约束

顾名思义,对类的构造函数进行了一定的约束,举个例子:

public class NoDefaultAccount : IAccount {
        private string name;
        public string Name {
            get {
                return name;
            }

        }

        private decimal balance;
        public decimal Balance {
            get {
                return balance;
            }
        }

        public NoDefaultAccount(string name) {
            this.name = name;
            this.balance = 0;
        }
    }


    public class Account : IAccount {
        private string name;
        public string Name {
            get {
                return name;
            }

        }

        private decimal balance;
        public decimal Balance {
            get {
                return balance;
            }
        }
        public Account(string name = "", decimal balance = 0) {
            this.name = name;
            this.balance = balance;
        }
    }


    public class AccountDrived : Account {
    }


    public class MyClass3<T> where T : class, new(){

        public MyClass3(){
            Console.WriteLine("In MyClass3<T> Ctor");
        }
    }

    class Program {
        static void Main(string[] args) {

            //1.MyClass3<Account> a = new MyClass3<Account>();
            MyClass3<AccountDrived> b = new MyClass3<AccountDrived>();//默认生成一个无参构造函数
            //2.MyClass3<NoDefaultAccount> c = new MyClass3<NoDefaultAccount>();//必须是有默认构造函数的非抽象类
        }
    }

这里的重点是public class MyClass3<T> where T : class, new(),这表明参数T对应的类型必须是一个引用类型(class),new()表示具备无参构造函数。

NoDefaultAccount类内显然没有默认的构造函数,在Account中有public Account(string name = "", decimal balance = 0),给定了默认值,在AccountDerived中,由于我们没有显式的声明一个构造函数,于是C#会自动生成一个AccountDerived()。

令人疑惑的是,Account是有默认构造函数的,为何//1.MyClass3<Account> a = new MyClass3<Account>();这条语句编译器会报错呢?
尝试后发现,C#和C++不一样,当你写下Account a = new Account();这条语句的时候,编译器会优先查找是否有public Account(),如果存在那么就构造对象,否则查找public Account(value = defaultvalue)这种带默认值的构造函数,两者是不一样的,并且是可以共存的。

class Account{
       //和C++不同,这并不是重定义
        public Account() {
            this.name = "xxxxx";
            this.balance = 10;
        }

        public Account(string name = "", decimal balance = 0) {
            this.name = name;
            this.balance = balance;
        }
 }

new()这种约束特指是否存在 Account()这样的无参默认构造函数。

函数方法的约束

这种形式就比较简单了,上述三个约束不加在泛型类中,加在函数中即可,举个例子:

 public class Algorithm {

        public static decimal Total<TAccount>(IEnumerable<TAccount> e) 
                              where TAccount : IAccount
        //这意味着调用Total函数传入的参数e必须是1.实现了IEnumerable接口的可迭代对象 2.e的可迭代元素必须是实现了IAcoount接口的
        {
            decimal total = 0;
            foreach(TAccount element in e) {
                total += element.Balance;
            }
            return total;
        }

        public static void Add<T>(T lhs, T rhs) where T : class, new() {
            //约束了T必须是引用类型,且必须定义了默认构造函数
            T ans = new T();
        }
    }


class Program {
        static void Main(string[] args) {

            List<Account> accounts = new List<Account>();

            accounts.Add(new Account("sixday", 100));
            accounts.Add(new Account("fiveday", 50));
            accounts.Add(new Account("sevenday", 70));

            Console.WriteLine("The answer is {0}", Algorithm.Total<Account>(accounts));

        }
    }

泛型类型约束总结

最后,做一个小总结:

  • where T : struct 这表明T必须是一个值类型,像是int,decimal这样的
  • where T : class 这表明T必须是一个引用类型,像是自定义的类、接口、委托等
  • where T : new() 这表明T必须有无参构造函数,且如果有多个where约束,new()放在最后面
  • where T : [base class name] 这表明T必须是base class类获其派生类
  • where T : [interface name] 这表明T必须实现了相应的接口

更多例子可以参考MSDN

where (查询表达式)

除了用于泛型约束之外,where还常用于查询表达式,可以直接参考MSDN的例子。

C# where

阅读数 1868

C# where()筛选方法

阅读数 2563

C# where泛型约束

阅读数 1915