精华内容
下载资源
问答
  • c#泛型约束
    2022-07-31 17:48:00

    五大泛型约束

    约束说明
    T : 结构T必须是值类型。可以指定除 Nullable 以外的任何值类型。
    T : 类T必须是引用类型,包括任何类、接口、委托或数组类型。
    T : 接口名称T必须继承该接口,并实现其中的所有方法。可以指定多个接口约束。
    T : 类名称T必须该类本身或者继承其的基类类。
    T : new()T必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。

    代码示例

    1.结构约束

    代码案例:

    static void Main(string[] args)
    {
    	List<int> listint = new List<int>();
    }
    
    //T : struct  必须是值类型
    public class List<T> where T : struct{}
    

    2.类关键字约束

    代码案例:

    static void Main(string[] args)
    {
    	List<string> liststring = new List<string>();
    }
    
    //T : class  必须是引用类型
    public class List<T> where T : class {}
    

    3.接口名称约束

    代码案例:

    static void Main(string[] args)
    {
    	List<B> listB = new List<B>();
    }
    
    //T : C  继承接口并实现接口中所有方法
    public class List<T> where T : C {}
    
    public interface C
    {
        bool Add();
        bool Edit();
    }
    
    //B继承接口C,因为C中含有方法,所有需将其全部实现
    public class B : C
    {
        public bool Add()
        {
            throw new NotImplementedException();
        }
    
        public bool Edit()
        {
            throw new NotImplementedException();
        }
    }
    

    4.类名称约束

    指出某个类型必须将指定的类作为基类(或者就是该类本身),才能用作该泛型类型的类型参数。
    代码案例:

    static void Main(string[] args)
    {
    	List<A> listA = new List<A>();
        List<B> listB = new List<B>();
    }
    
    //T : A  类本身或其基类
    public class List<T> where T : A {}
    
    public class A {}
    
    //B是A的基类
    public class B : A {}
    

    5.new()约束

    new() 约束可以让编译器知道:提供的任何类型参数都必须具有可访问的无参数(或默认)构造函数。
    代码案例:

    static void Main(string[] args)
    {
    	List<A> listA = new List<A>();
    }
    
    //T : A, new()  类本身或其基类,同时要包含无参构造函数
    public class List<T> where T : A, new() {}
    
    //默认就有无参构造函数
    public class A {}
    
    更多相关内容
  • where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量。1.接口约束。例如,可以声明一个泛型类 MyGenericClass,这样,类型参数 T 就可以实现 IComparable<T> 接口: 代码如下:public class...
  • c#泛型约束

    2022-07-31 16:19:31
    泛型约束的使用以及可作用场景

    1.泛型约束的使用

    泛型约束的作用
    在一个泛型方法或者说泛型接口中,传入的泛型是不确定的,但是在方法体中,我们传入一个实体,要在代码块中获取实体的各种属性如:姓名、性别等,但是问题来了,由于我们的类型是在调用的时候确定的,因此在写泛型方法或接口代码的时候我们是不确定入参类型,所以就需要一个东西来确定入参有那些属性,由此 泛型约束就冒出来了,当然 为了更好的理解 下面有代码解释—以泛型方法为例:
    首先我们定义一个动物类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace StudyComm.ClassFolder
    {
        /// <summary>
        /// 动物
        /// </summary>
        public class AnimalClass
        {
            /// <summary>
            /// 动物种类
            /// </summary>
            public string AnimalType { get; set; }
    
        }
    }
    

     然后再定义一个鸟类  和狗类 继承自动物

    public class BirdClass : AnimalClass
    {
        /// <summary>
        /// 鸟类名字
        /// </summary>
        public int BirdName { get; set; }
    
    }
    public class DogClass : AnimalClass
    {
        /// <summary>
        /// 狗的种类
        /// </summary>
        public string DogType { get; set; }
    }
    

    我们再定义一个人类

    /// <summary>
    /// 人类
    /// </summary>
    public class HumanClass
    {
        /// <summary>
        /// 名字
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 国籍
        /// </summary>
        public string Nationality { get; set; }
    }
    

    再来一个中国人和日本人

    /// <summary>
    /// 定义一个中国人的类,并继承人类
    /// </summary>
    public class ChineseClass : HumanClass
    {
        /// <summary>
        /// 身份证
        /// </summary>
        public string IDCard { get; set; }
    }
    /// <summary>
    /// 定义一个日本人
    /// </summary>
    public class JapaneseClass : HumanClass
    {
    	//这里面我就不加属性 因为日本人是直接继承人类  所以也具有名字和种类
    }
    

    在写好了类之后 ,我来写几个方法 在每个方法中 使用泛型约束 规定在调用的时候传入的参数必须为指定类及其子类

    public class FunClass
    {
        /// <summary>
        /// 用于展示中国人的名字
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Type"></param>
        public static void ShowHuman<T>(T Type) where T : HumanClass//泛型约束为  HumanClass类,表示只能传入人类  以及其子类
        {
            Console.WriteLine($"这个人是一个{Type.Name},他的国籍是{Type.Nationality}");
        }
        public static void ShowBirdType<T>(T Type) where T : AnimalClass//泛型约束为  AnimalClass类,表示只能传入动物类  以及其子类
        {
            Console.WriteLine($"这个动物的种类是{Type.AnimalType}");
        }
    }
    

    我们在方法里实例化两个人 一个中国人,一个日本人

    //实例化一个中国人,日本人
    ChineseClass chinese = new ChineseClass() { Name="小明",Nationality="中国"};//中国人
    JapaneseClass human = new JapaneseClass() { Name = "小岛秀夫", Nationality = "日本" };//日本人
    

    上面实例化的两个人都是继承自HumanClass类 所以在调用的时候

     //我们在调用的时候<>中可以指定类型为HumanClass
     FunClass.ShowHuman<HumanClass>(chinese);//传入中国人
     FunClass.ShowHuman<HumanClass>(human);//传入日本人
     //当然  我们也可以把具体的类指定进去
     FunClass.ShowHuman<ChineseClass>(chinese);//传入中国人
     FunClass.ShowHuman<JapaneseClass>(human);//传入日本人
     //同时  我们也可以简写为
     FunClass.ShowHuman(chinese);//传入中国人
     FunClass.ShowHuman(human);//传入日本人
    
    • 以上三种写法都是可以的
    • 但是 如果我们实例化个鸟和狗之后,把鸟 或者狗传入ShowHuman方法 那么就会报错

     

     

    • 由于我们ShowHuman方法约束了传入的只能是HumanClass及其子类,传入的dog 是无法转化为Human等类型,故此报错
    • 泛型约束的可作用场景

    • 上面只是泛型方法的约束使用,但是泛型可用的地方总共有六种
    名称描述
    new()类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
    接口类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
    基类类型参数必须是指定的基类或派生自指定的基类。
    U为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。
    结构类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型
    类型参数必须是引用类型,包括任何类、接口、委托或数组类型

    例子:

    namespace StudyComm.Generic
    {
        class GenericConstraint<T> where T : GenericInterFace<T>//接口约束GenericInterFace为一个泛型接口
        {
        }
        class ClassOrStructureConstraint<T, A>//类或结构约束
        where T : HumanClass
        where A : AnimalClass
        {
    
        }
        public class ConstructorConstraint<T> where T: IComparable, new()//构造函数约束
        {
            //裸类型约束,当具有自己的类型参数的成员函数需要将该参数约束为包含类型的类型参数时可使用
            void UConstraint<U>(List<U> list) where U : T
            { }
        }
    
    }
    

    展开全文
  • C#泛型约束

    千次阅读 2022-05-24 20:08:10
    泛型的六种约束

    泛型约束一共有六种:

    约束的是字母T,程序中调用的T是什么类型,就要用什么样的类型

    1.值类型,where 泛型字母:struct;

    Class Test1<T> where T:struct
    {
        public T value;
        
        public void TestFun<K>(K v) where K:struct
        {
            
        }
    }

    以上是定义了值类型为struct的类,里面有变量和方法

    如果在主函数中声明为

    Test1<Object> t=new Test1<Object>();
    Vs会报错

    为何会报错?转到定义可知

    Objcet是引用类型

    换成Test1<int> t=new Test1<int>();

    //无报错
    //再举例Test1中的函数
    t.TestFun<Random>(new Random());
    //会报错

    因为Random也是引用类型

     改为t.TestFun<float>(1.4f);

    转到速览定义float可知,float是结构体

    2.引用类型,where 泛型字母 class

    值类型声明的Object和Random在引用类型不会报错,因为约束的字母T就是要用引用类型填入

    3.存在无参公共构造函数,where 泛型字母:new()

    举例来说 还是定义一个Test类 类中也有变量和函数 此外 再声明两个类 一个有默认构造函数 一个自定义了一个构造函数

    Class Test<T> where T:new ()
    {
        public T value;
    
        public void TestFun<K>(K k) where K:new ()
        {
        
        }
    }
    Class Test1
    {
    }
    Class Test2
    {
        public Test2(int a){}
    }
    

    回到主函数

    Test<Test1> t=new Test<Test1>();//不会报错 test1默认有无参构造函数

    但是 要是将test1换为test2 则会报错 因为test2中的无参构造函数被顶掉了

    当然 要是test1将自己的无参构造函数设置为private 注意这种类型约束说的是无参公共构造函数 将test1中的无参构造函数的访问级别设置为private 则程序会报错

    题外话:结构体中即使写了有参构造 无参构造并不会被顶掉 所以将test1换成struct类型的结构体 不会报错

    那么,抽象类呢?要清楚 抽象类是不能new的 既然不能new 那么Test<Test1> t=new Test<Test1>();会报错

    4某个类本身或者其派生类,where 泛型字母:类名

    class Test<T> where T:Test1
    {
        public T value;
        public void TestFun<K>(K v) where T:Test1{};
    }
    class test1{}
    class test2:test1{}

    回到主函数声明一个类

    Test<test1>() t=new Test<test1>();//无报错

    Test<test2>() t=new Test<test2>();无报错 test2是test1的派生类

    问号:如果是Object类呢?不可以 Object是所有类的父类 也就是说Object是test1的父类 test1的子类和它本身可以填入 但是语法未规定test1的父类也可以填入

    5.某个接口的派生类型,where 泛型字母:接口名

    接口和4一样 

    class test1:Ifly{}
    c;ass test<T> where T :Ifly
    {
        public T value;
        public void TestFun<K>(K k) where T:Ifly{}
    }
    //Main函数
    test<test1>() t=new test<test1>();
    test1继承Ifly接口 所以未报错
    

    6.另一个泛型类型本身或派生类型.where 泛型字母:另一个泛型字母

    class test<T,U> where T:U
    {
        public T value;
        public void TestFun<K,V>(K k) where T:V{};
    }
    解析:要不U是T本身 要不T是U的派生类
    

    7.问题:以上泛型约束是否可以组合使用

    回答是肯定的.

    class test<T> where T:class,new(){}//这个组合可以
    class test<T> where T:struct,new(){}//报错 
    struct有公共的无参默认构造函数 再写new()就画蛇添足了
    简而言之 泛型约束之间进行组合使用 无明确规则 语法和实际使用时不冲突就行

    8.如果有多个需要约束的泛型呢?

    举个例子就清楚了

    class test<T,K> where T:class,new() 
                    where K:class,new()
    {}

    写完第一个约束 接着写第二个泛型约束就行

    趁热打铁:在泛型六种约束的基础上 写一个单例模式基类

     

    展开全文
  • C# 泛型约束讲解

    2021-04-29 19:28:48
    C# 泛型约束讲解为什么加约束约束关键字格式约束类型关键字各各类型实例值类型约束 ==struct==引用类型约束 ==class==无参构造函数 ==new()==某一类本身或者其派生类 ==T:类名==某一接口其派生类 ==T:接口名==另一...

    为什么加约束

    当我们用泛型很爽的时候,有人说适当的加上约束比较好。可是为什么呢?
    因为泛型是可以任意类型的,此时就有潜在的危险,当我们滥用泛型时就可能搞不清我们的泛型是什么类型的了,所以为了代码的可读性和结构性,我们要给泛型加上约束。

    约束关键字

    where
    举个简单的例子

    class test<T>where T:new()
    {
    } 
    

    格式

    <泛型字母> where 泛型字母:约束类型关键字

    约束类型关键字

    1. 1.值类型 Struct (整型,浮点型,十进制类型,Bool类型,枚举类型,可谓NULL类型) bool,byte,char,decimal,double,float,int,long…
    2. 引用类型 Class(对象类型,动态类型,字符串类型)对象类型:类,Object 动态类型:数组,委托,集合array…
    3. 存在无参公共构造函数 new()
    4. 某一类本身或者其派生类 泛型字母:类名
    5. 某一接口其派生类型 泛型字母:接口名
    6. 另一泛型类型本身或者派生类型 泛型字母:另一个泛型字母
      c#数据类型

    各各类型实例

    值类型约束 struct

    class Test1<T>  where T:struct
        {
            public T value;
    
            public T GetT<T>(T v)
            {
                return v;
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Test1<int> test1 = new Test1<int>();
                test1.value = 10;
                Console.WriteLine(test1.GetT(test1.value));
            }
        }
    

    引用类型约束 class

    class Test2<T> where T:class
        {
            public T value;
    
            public T GetT<T>(T v)
            {
                return v;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Test2<string> test2 = new Test2<string>();
                test2.value = "皮学渣真帅";
                Console.WriteLine(test2.GetT(test2.value));
            }
        }
    

    约束类型不匹配的话会报错
    在这里插入图片描述
    int是值类型不是引用类型

    无参构造函数 new()

     class Test3<T> where  T:new()
        {
            public T value;
            
        }
    
        class Test4
        {
            public Test4()
            {
                Console.WriteLine("我是无参构造函数Test4");
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Test3<Test4> test3 = new Test3<Test4>();
                test3.value = new Test4();
            }
        }
    

    运行结果:
    在这里插入图片描述

    某一类本身或者其派生类 T:类名

     class Test4
        {
            public Test4()
            {
                Console.WriteLine("我是无参构造函数Test4");
            }
        }
      class Test5:Test4//做一个test4的派生类
        {
            public Test5()
            {
                Console.WriteLine("我是Test5的构造函数");
            }
        }
    
        class Test6<T> where  T:Test4
        {
            public T value;
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                Test6<Test4> test6 = new Test6<Test4>();
                test6.value = new Test4();
                test6.value = new Test5();
                Test6<Test5> test7 = new Test6<Test5>();
                test7.value = new Test5();
            }
        }   
    

    运行结果:
    在这里插入图片描述
    运行结果看不懂的要复习构造函数了…

    某一接口其派生类 T:接口名

    	interface IFly
        {
            public void fly();
        }
    
        interface IRun:IFly
        {
            public void run();
        }
        class Test4:IFly
        {
            public Test4()
            {
                Console.WriteLine("我是无参构造函数Test4");
            }
    
            public void fly()
            {
                Console.WriteLine("Test4的接口fly");
            }
        }
    
        class Test5 : Test4
        {
            public Test5()
            {
                Console.WriteLine("我是Test5的构造函数");
            }
        }
    
        class Test7 : IRun
        {
            public void fly()
            {
                Console.WriteLine("Test7的接口fly");
            }
    
            public void run()
            {
                Console.WriteLine("Test的接口run");
            }
        }
    
        class  Test8<T> where  T:IFly
        {
            public T value;
        }
     class Program
        {
            static void Main(string[] args)
            {
                Test8<IFly> test8 = new Test8<IFly>();
                
                test8.value = new Test4();
                IFly hFly = test8.value;
                hFly.fly();//显示转换成接口
                test8.value = new Test5();//该代码说明基类继承了约束接口就可以转换。
                test8.value = new Test7();//该代码说明就算是接口相互继承,类继承了派生接口也是可以转换的。
            }
        }
    

    运行结果:
    在这里插入图片描述

    另一泛型类型本身或者派生类型 T:K

     	interface IFly
        {
            public void fly();
        }
    
        class Test9 : IFly
        {
            public Test9()
            {
                Console.WriteLine("我是无参构造函数Test9");
            }
    
            public void fly()
            {
                Console.WriteLine("Test9的接口fly");
            }
        }
    
        class Test10<T,K> where T:K
        {
            public T value;
        }
    	class Program
        {
            static void Main(string[] args)
            {
    
                Test10<Test9, IFly> test10 = new Test10<Test9, IFly>();
                test10.value = new Test9();
                test10.value.fly();
            }
        }
    

    运行结果:
    在这里插入图片描述
    这一个约束可以看成第一个约束字母继承第二个约束第二个约束字母的,或者是第一个字母本身。

    两个约束一样

    class Program
        {
            static void Main(string[] args)
            {
                Test10<Test9, Test9> test10 = new Test10<Test9, Test9>();
                test10.value = new Test9();
                test10.value.fly();
            }
        }
    

    运行结果
    在这里插入图片描述

    字母多重约束

    单一字母多重约束

    	class Test<T> where T:class,new()
        {
            
        }
    

    这样的话根据上述六个约束类型可以相互组合,但是并不是任意两种就可以组合的。
    组合的时候一样要注意顺序和组合类型

    不可组合类型例子

    在这里插入图片描述

    顺序组合错误

    在这里插入图片描述

    多个字母多重约束

    	class Test<T,K> where T:class,new() where K:class,new()
        {
            
        }
    

    第一个字母约束设置好后直接跟下一个字母进行约束,中间不加符号

    展开全文
  • 主要介绍了C#泛型的类型参数约束的相关资料,文中讲解非常细致,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下
  • C# 泛型约束为枚举

    2021-09-27 18:12:06
    示例:根据权重对象列表随机返回一个枚举类型 using System.Collections; using UnityEngine; public static class WeightObjectsUtil { /// <summary>... /// 随机在权重列表返回一个枚举类型 ...
  • C# 泛型约束

    2020-12-31 17:30:47
    1.引用类型约束 struct RefSample<T> where T:class 引用类型用Class表示约束,其他的引用类型为具体的约束。 表示对于的约束必须为一个类(引用类型)不能是值类型(int,char,datatime,struct),可以是接口...
  • 访问修饰符 返回类型 泛型方法名 (T 参数)1):无法在泛型方法内部给任何 T 类型创建实例的对象,因为在泛型方法内部不知道传进来的对象有哪些构造函数2):约束是对内部的!(对于泛型方法)约束也是会被继承的!3...
  • C#泛型泛型约束

    2021-08-17 21:36:58
    二、泛型约束: 在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是...
  • 关于C#泛型约束 你好! 这是 泛型约束 所展示的欢迎页。 文章目录关于C#泛型约束1.这得从类说起**1>类:**1.1>.类的定义1.2> C#中的类【3种:抽象、密封、非抽象】1.3> C#中的类的赋值1.4> base的...
  • C#泛型约束

    2021-06-03 15:47:40
    最近在看一些项目和框架,用了好多泛型,虽然C++模板比较熟,但是泛型却接触的比较少,所以看了CLR的泛型后打算写个文章记录下方便以后自己看。(其实和模板差不多!) 泛型 介绍 泛型是CLR和编程语言提供的一种特殊...
  • https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
  • C#泛型泛型约束

    千次阅读 2019-01-24 11:36:27
    为什么要使用泛型 考虑一种堆栈类 class Stack { public string[] Elements { get; set; } public int Current { get; set; } public string Pop() { return Elements[Current]; ...
  • 泛型约束的意思就是说:类的泛型,只能是where字句后面所写的接口或类。这么说好像也有点不大明白,举个例子。我有一个接口,如下: 代码如下: /// /// 国籍的接口 /// public interface INationality { ...
  • 前言上一篇博文简单介绍了泛型约束,说是通过where<>来实现具体委托占位符的约束。那么约束又有什么类型和次序呢。这篇文章咱们一起看看。目前共5种类型的约束。类名:只有这个类...
  • 解决C#泛型约束与无法创建带参数的泛型实例的矛盾问题提出问题分析解决方案基于反射的解决方案基于表达式目录树的解决方案代码附录反射解决方案完整代码表达式目录树解决方案完整代码 问题提出 有时候我们在项目中,...
  • C# 泛型,泛型约束

    2019-02-21 15:27:00
    泛型主要是为了解决代码的复用性 在泛型出现之前,如果需要用到不同的参数类型,但是方法体一样的时候,需要定义多个不同类型参数的方法,这样有太多的重复代码如下  public static void ShowInt(int i...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,245
精华内容 4,498
关键字:

c#泛型约束