首页 > 知识百科 > 正文

C泛型概念及方式详解原创

一、泛型的定义及作用

泛型(generic)是C# 2.0推出的新语法,它专门用于处理多段代码在不同的数据类型上执行相同的指令的情况而设计的。比如说编程时,功能非常相似的模块,只是它们所处理的数据类型不同,但是我们却需要写不同的方法来实现它,很明显,这加大了我们的工作量,也很乏味。有什么办法能够解决这个问题呢?它就是泛型了,可以让多个类型共享一组代码。通过压栈例子可以更清晰的了解泛型

 class IntStack {int[] arr;公共无效推(int x){...}; //将int类型的值压栈 } class FloStack {float[] arr; public void push(float x) { ...};//将float类型的值压栈 }

这两类功能一样,只是操作的数据类型不同,并且如果需要新类型(double、string)等时,又需要进行重复的操作,下面介绍怎么通过类型泛化解决这个问题

二、泛型的使用

class MyStack  { T[] arr;公共无效推(T x){...}; }

  创建泛型类时,先在类名后面添加,放置类型占位符T替代int或float。由尖括号和T构成的字符串说明T是类型的占位符(不一定是字母T,也可以是其他标识符)。

<泛型类型不是类型,而是类型的模板,只要比类型不是对象对象的模板一样。< /p>

C#提供了五种泛型:类、结构、接口、委托和方法。前面四种是类型,而方法是成员。还是很迷吧,接下来对五种泛型分别进行讲解。

  1、泛型类型类

由于泛型类不是实际的类,而是类的模板,所以我们必须先从它们构造出实际的类类型,然后创建这个构造后的类类型的实例。

从泛型类型创建实例的过程是:a:声明泛型类型 b:通过提供真实类型创建构造类型 创建 c: 从构造类型实例<<

> ="img-center">

使用 System;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Threading.Tasks;命名空间泛型{ class Test//构造泛型类,T1,T2为类型参数 { public T1 var1;公共 T2 var2; public void print() { Console.WriteLine("var1:{0} var2:{1}", var1 , var2); } } class Program { static void Main(string[] args) { // 两种实例化的方式,效果相同 Test first = new Test();//int和string为类型实参,分别对应T1,T2 var secondary = new Test();首先.var1 = 123; //第一个中,var1只能为int类型,当然也可以通过强制类型转换成其他的类型。var2 = "Good Luck!"; // 只能为string类型,同上first.print();第二个.var1 =“你好世界”;第二个.var2 = 345;第二个.print(); Console.ReadKey(); } }}

  

同一个泛型可以构建出很多不同的类型,互不干扰,每个都有独立的类类型,就需要有独立的非泛型类声明一样

<

<2、泛型结构

struct MyStruct{ public T val;}

和泛型类类似,不过多叙述

<3、泛型委托

泛型委托和非泛型委托非常相似,不过类型参数决定了它能接受什么方法

delegate S MyDel (T value) ;//S为委托返回类型,T为委托参数类型

<4、泛型接口

使用 System;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Threading.Tasks;命名空间泛型{ 接口 Test { void Print(T value); } } /* * 泛型的接口实现必须唯一,必须保证类型参数组合不会再类型中产生两个重复的接口* class Simple : Test, Test 是错误的,因为S有可能是int类型 * 你也可以再非泛型类型中实现类型泛接口 * class Simple : Test, Test */ class Simple : Test { public void Print(S value) { Console.WriteLine("值为 {0}",value); } } } class Program { static void Main(string[] args) { var IntSimp = new Simple(); var StrSimp = new Simple<字符串>(); IntSimp.Print(123); StrSimp.Print("你好世界"); Console.ReadKey(); } }}

注意:泛型接口的名称和非泛型接口不会冲突,我们可以在前面的代码中声明一个测试的非泛型接口,程序能正常执行

<5、泛型方法

<泛型方法有两个参数列表,封闭在圆括号内的方法参数列表和在尖括号内所示的类型参数列表,如下<

public void Print (S val1, T val2){ ...}

三、类型参数的约束(constraint)

顾名思义,即对类型参数进行约束,让编译器知道参数可以接受哪些类型,只有符合约束的类型才能替代给定的类型参数,来产生构造类型

对此,可以使用where子句,其语法为:  where TypeParam :constraint,constraint ... 

一个where对应一个类型参数,如果类型参数有多个约束,则用分隔符

class Test where T : IComparable where S : new() ​​{...}​​​​ //不理解没关系,下面会讲 //注意两个地方之间没有任何符号分隔,可以以任意顺序排列

​ ,有五种约束类型

其中子句的约束必须有特定的顺序

  a:最多只能有一个主约束,如果有则必须放在上层,主约束可以为结构、类别或基类名

  b:可以有任意多个的接口名约束,其类型为接口名称

:如果存在构造函数约束,则必须放在最后面,构造函数约束即为 new()

四、协变和预警 

“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

“预警”则指能够使用派生程度更小的类型。

可以显式使用关键字指定类型参数的协变,用在关键字指定类型参数的波形中

接口 IItf {...}delegate void Test(T a);

使用in和out关键字的显着变化方式只适合于委托和接口,不适用于类、结构和方法

/******************************************** ******C#根据泛型指定方法的返回值类型

在编写程序的时候经常会查询同一个方法有多次重载,其生成参数相似,只是类型不一致。如下所示:

        public double GetData(){    }
 
        public string GetData(){    }
 
        public int GetData() {    }
        对方法进行重载那么宽度程序封装肿胀,有没有更好的方法解决呢?

       这里我们采用泛型解决方案,具体代码实现如下:

        public static T GetData()
        {
            类型 t = typeof(T);
            if(t == typeof(Double))
              {
                double result = 1.00009;
                return (T)(Object)result;
            }
              else if(t == typeof(string))< br />             {
                string result = "这是字符串类型";
                return (T)(Object)result;
            }
            return default( T);
        }
这是测试方法和测试结果

        public static void Main(string[]args)
        {
            string result1 = GetData();
            Console.WriteLine(result1); // 这是字符串类型
 
            double result2 = GetData();
            Console.WriteLine(result2); //1.00009
            Console.ReadKey();
        }
          

       当然这个方法除了解决实体参数作为泛返回型的问题外,还有另外的用处是:在调用方法时指定返回值类型,例如Newtonsoft.Json中json对象的反序列化就是这样用的。

List result = Newtonsoft.Json.JsonConvert.DeserializeObject>(jsonStr);
/******************************************** ************c#带返回值的action_C#委托和匿名函数大总结

一、匿名函数
匿名函数是一个“内联”语句或表达式,可以在需要委托类型的任何地方使用。可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数。

C#中有两种匿名函数:Lambda表达式和匿名方法。

二、C#中委托的发展历程
C# 1.0中,您可以通过在使用代码中位置定义的方法显式初始化委托来创建委托的实例。

C# 2.0 引入了其他匿名方法的概念,作为一种编写的可在委托调用中执行的未命名内联语句

C# 3.0 引入了 Lambda 表达式,这种表达式与匿名方法的概念类似,但增加了表达力并且更简单练。这两个功能系统称为“匿名函数”。通常,针对 .NET Framework 版本 3.5 及更高版本的应用程序应使用 Lambda 表达式。

测试代码如下:

  public class HistoryDe​​legate
    {
        private delegate void Delegate1(string str_);
        private void OnDelegate1(string str1_)
        {
            Console.WriteLine($" OnDelegate1: {str1_}");
        }
 
        public void OnTest()
        {
            //C# 1.0
Delegate1 d1 = new Delegate1(OnDelegate1);
            d1("d1");
            //C# 2.0
            Delegate1 d2 = delegate (string str) { Console.WriteLine($"{str} ”); };
            d2("d2");
            //C# 3.0
            Delegate1 d3 = (x) => { Console.WriteLine($"{x}"); };
            d3("d3");
        }
    }
三、C#内置泛型委托
Action委托:

Action是无返回值的泛型委托。

Action表示无参,无返回值的委托

Action 表示有确定参数int,string无返回值的委托

Action 表示有确定参数int,string ,bool无返回值的委托

Action 表示有确定4个int型参数,无返回值的委托

Action至少0个参数,至多16个参数,无返回值。

测试代码如下:

    public class TestAction
    {
        private void OnAction1(string str_)
        {
            Console.WriteLine($"OnAction1:{str_}");
        }
        private void OnAction2(int index_ , string str_) => Console.WriteLine($"OnAction1:{index_}/{str_}");
 
        public void OnTest()
        {< br />             Action action1 = new Action(OnAction1);
            action1("action1");
            Action action2 = new Action(OnAction2 );
            action2(2, "action2");
        }
    }
Func委托

Func是有返回值的泛型委托,<>中,最后一个类型为返回值类型。

Func 表示无参,返回值为int的委托

Func 表示格式化参数为object, string 返回为int的委托

Func 表示确定参数为object, string返回为int的委托

Func 表示确定参数为T1,T2,,T3(泛型)返回值为int的委托

Func至少0个参数,至多16个参数,根据泛型返回值返回。必须有返回值,不可void

测试代码如下:

    public class TestFunc
    {
        private string OnFunc1( int index_, string str_)
        {
            Console.WriteLine($"OnFunc1:{index_}/{str_}");
 
            return str_ ;
        }
        private int OnFunc2(string str1, string str2_)
        {
            Console.WriteLine($"OnFunc2:{str1}/{str2_ }");
            return 1;
        }
        私有字符串 TestFunc1(Func func_, T1 index_, T2 str_)
        {
            return func_(index_, str_);
        }
        public void OnTest()
        {
            Console.WriteLine(TestFunc1(OnFunc1, 1, "index"));
 
            Func func2 = new Func(OnFunc2);
            Console.WriteLine(func2("name1", "name2"));< br />         }
    }
Predicate委托

Predicate是返回bool型的泛型委托

Predicate表示格式化参数为int Returnbool的委托

Predicate有且只有一个参数,返回值固定为bool

测试代码如下:

  public class TestPredicate
    {
        private bool OnPredicate1(int index_)
        {
            if (index_ > 0)
            {< br />                 return true;
            }
            else
            {
                return false;
            }
        }
 
        private bool TestPredicate1(Predicate predicate1, T index_)
        {
            return predicate1(index_);
        }
        public void OnTest()
        {
            Console.WriteLine(TestPredicate1(OnPredicate1) , 0));
        }
    }
总结:

委托类似于C++函数指针,但它们是类型安全的。

委托允许将方法作为参数进行提交。

委托可用于定义回调方法。

委托可以链接在一起;例如,可以对一个事件调用多个方法。

方法不一定与委托签名完全匹配。

委托至少0个参数,至多32个参数,可以无返回值,也可以返回指定值类型

Func可以接受0个至16个格式化参数,必须有返回值

Action可以接受0至16个格式化参数,无返回值

Predicate只能接受一个格式化参数,返回值为bool类型

四、优化技巧
1.问题避免函数引用外部变量,使其可被静态化

2.搞清楚哪些变量被匿名函数引用了,防止内存泄漏

3.尽量把被引用的变量声明放在后面,用变量复制来延迟匿名函数创建

//错误的写法

void Error1() 
{
    var printList = new List();
    for ( int i = 0; i < 10; ++i ) {
        // 内部循环一直在构造匿名函数对象,分配大量的内存
        printList.Add( () => Debug.Log( i ) );
    }
    for ( int j = 0; j < printList.Count; ++ j ) {
        printList[ j ](); // 结果总是输出10
    }
}
 
void Error2() 
{
    var list = new List ();
    list.Add( 1 );
    list.Add( 2 );
 
    int id = 0;
 
    if ( id == 5 ) 
    {  
        // 假设遇到问题
        // 表面上看,匿名函数对象在构造这里
        // 但实际上,匿名对象在id声明处就已经提前构造好了
        //这样会100%造成内存分配
        list.Find( value => value == id );
    }
}
//正确的写法

void Error1()
{
    var printList = new List();
    for ( int i = 0; i < 10; ++i )
    {
        // 为了避免循环变量被引用
        // 复制i到局部变量,让其被匿名函数引用
        var _i = i ;
        printList.Add( () => Debug.Log( _i ) );
    }
    // 结果虽然是对的,但实际上编码中,还是要避免循环中构造匿名函数
    // ...
}
 
void Error2() 
{
    var list = new List ();
    // ...
    int id = 0;
    if ( id == 5 ) 
    {
        //同理,这样匿名函数构造的位置操作延迟到了表达式内部
        // 消除大部分时候的内存分配
        var _id = id;
        list.Find( value => value == _id );
    }
}
五、常用技巧写法
    public class TestProperty
    {
        //定义接口属性
        public string Name => "Hello";
        private string m_name1 = "World";
        public string Name1 => m_name1;
 
        // 给定义属性默认值
        public int Age { get;放; } = 18;
        private int m_age1 = 18;
        public int Age1
        {
            get { return m_age1; }
            set { m_age1 = value; }
        }
        private Predicate onRule;
 
        public void OnTest()
        {
            // 匿名函数的简洁写法:可以省掉,参数列表括号,函数体括号,返回语句
            List list = new List() { "aaa", "bbb", "name" };< br />             string result1 = list.Find(x => x == "name");
            string result2 = list.Find((x) => { return x == "ccc"; });< br />             if (null == result2)
            {
                Console.WriteLine("未找到 ccc");
            }
            if (null = = onRule)
            {
                onRule =OnRule;
                string reslut3 = list.Find(onRule);
            }
 
        }
 
        private bool OnRule(string str_)
        {
            if (str_ == "aaa")
            {
                Console.WriteLine("OnRule查找aaa");
                return true;
            }
            else
            {
                Console.WriteLine("OnRule 找不到 aaa");
               返回 false;< br />             }
        }
    }
/******************************** ********

C#委托、泛型委托、匿名委托、lambda表达式

1、为什么要使用委托
将一个方法作为参数传递给另一个方法

2、委托概念
声明:

public delegate int DelegateName(int a, int b);
1
声明一个委托类型,可以用访问修饰符修饰,委托关键字,有返回值和参数

委托所指向的函数必须跟委托相同的签名,即相同的参数个数,相同的参数类型和相同的返回值类型

创建委托实例写法:
委托委托名=new委托(会调用的方法名)
或者:
委托委托名=会调用的方法名

3、泛型委托
声明:

public delegate T委托名(T a, T b);
1
我们每次要使用一个委托时,都需要先这个声明委托类,规定参数和返回值类型,然后才能实例化、调用。为了简化这个过程,.NET框架为我们封装了三个泛型委托类,它们分别是Action,Func和Predicate。因此大部分情况下我们不需要再声明委托,可以拿来直接实例化使用,方便了我们的日常编码。

1). Action

public delegate void Action(T obj1,Tobj2,...);
1
Action是无返回值的泛型委托

Action 表示无参,无返回值的委托

Action 表示有确定参数int,string 无返回值的委托

Action 表示有确定参数int,string,bool无返回值的委托

Action 表示有确定4个int型参数,无返回值的委托< /p>

Action 至少 0 个参数,至多 16 个参数,无返回值。

创建委托实例写法:
Action<参数1, 参数2> 委托名= ((参数1,参数2) => {无返回值的方法体});

2). Func

public delegate Func(T obj1,Tobj2,...);
1
Func是有返回值的泛型委托

函数表示无参,返回为int的委托

Func 表示确定参数为object, string返回为int的委托

Func 表示确定参数为T1,T2,T3(泛型)返回值为int的委托

Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

创建委托实例写法:
Func<参数1, 参数2, 返回值> 委托名= ((参数1,参数2) => { 带方法体的返回值 });

3). Predicate

  public delegate bool Predicate(T obj);
1
这个委托只能确定一个参数,并且如参参的类型由用户自行提供,返回一个bool类型的值。

Predicate 是返回bool型的泛型委托

Predicate 表示确定参数为int返回bool型的委托

Predicate有且只有一个参数,返回值固定为bool

创建委托实例写法:
Predicate<参数1>委托名= ((参数1) => {带返回值的方法体});

4、匿名函数(没有函数名,直接方法体)
本来呢委托定义(声明)好之后,还得再单独定义委托需要使用的方法。不如说你定义了一个外汇的委托,你还需要重新写计算加减乘除的方法来供外汇委托来使用。这个时候我们就想到了匿名方法。用匿名方法就不需要再单独写加减乘除了这些方法了,只需要在匿名方法的方法里面实现这些逻辑就好了。

例子如下:


        delegate int Calculator(int x, int y) ; //委托类型

static void Main(string[] args)
        {
            //创建委托对象(确定与哪些方法进行绑定),委托实例名=new委托名(某个)类的方法)本例与加法向绑定
           计算器添加 =delegate( int x, int y)
            {
               return x+y;
            };


            计算器 移动 = delegate(int x, int y)
            {
                return x - y;
};


            计算器 Multiply = delegate(int x, int y)
            {
                return x * y;
            } ;


            计算器 Divide = delegate(int x, int y)
            {
                return x / y;
            };
            加(4, 4);//8
            移动(4, 4);//0
            乘(4, 4);//16
            除(4, 4);//1

        }

创建委托实例写法:
委托 委托名=delegate(参数){会调用的方法体};

5、 Lambda 表达式
定义:“Lambda 表达式”是一个匿名函数,是一种高效的类似函数式编程的表达式

好处:Lambda简化了匿名委托的使用,减少了开发中需要编写的代码量。

具体内容:它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带可绑定到委托或表达式树的输入参数的内联表达式。

写法:所有Lambda表达式都使用Lambda表达式=>,该表达式读作“goes to”。Lambda表达式的左边是输入参数(如果有),右边是表达式或语句块。Lambda表达式x => x * x读作“x gets to x times x” 。

创建委托实例写法:
委托委托名=((参数1,。。参数n)=>{会调用的方法体});

六、调用委托实例通用写法:
1.委托实例.Invoke(参数列表)

2.委托实例(参数列表)

3.this.Invoke(委托实例, new object[] { 参数列表});
/********************************* ***使用Func委托返回对象

Func具有委托

封装一个两个参数并返回TResult参数指定的类型值的方法。

语法

 public delegate TResult Func(T1 arg1, T2 arg2) 
 T1此委托封装方法的第一个参数类型中的类型参数。该类型参数是预告。即可以使用指定的类型或派生程度不同的类型。关协变和逆变的更多信息,请参阅泛型中的协变和逆变。在T2中此委托封装的方法的第二个参数类型。out TResult此委托封装的方法的返回值类型。类型参数是协变类型。即可以使用指定的或派生程度更高的类型。有关协变和预报的更多信息,请参见泛型中的协变和预报。参数arg1类型:T1此委托arg2类型:T2此委托封装方法的第二个参数。返回值类型:TResult此委托封装方法的返回值。 

备注< /p>

使用此委托表示一种可以以参数形式提交的方法,而不用显式的自定义委托封装的方法必须与此委托定义的方法签名相对应。方法必须具有两个均通过值传递给它的参数,并且必须返回值。

取消引用两个参数并返回 void 的方法(或者要在 Visual Basic 中引用)被声明为 Sub 而不是被声明为 Function 的方法),请改用泛型 Action 委托。 

在使用 Func 委托时,不需要显式定义一个封装参数方法的委托。例如,以下两个代码显式声明了一个名为 ExtractMethod 的委托,并对 ExtractWords 方法的引用分配给其委托实例。

示例

下面的示例演示如何声明和使用 Func 委托。此示例声明一个 Func 变量,并将其分配给一个采用 String 值和Int32 值参数的 lambda 表达式。如果 String 参数的长度等于 Int32 参数的值,则此 lambda 表达式将返回 true。另外在查询中使用封装此方法的委托来作为筛选字符串中的字符串。< /p>

 使用 System;使用 System.Collections.Generic;using System.Linq;public class Func3Example{public static void Main(){Func 谓词 = (str, index) = > str.Length == index;String[] Words = { "orange", "apple", "Article", "elephant", "star", "and" };IEnumerable aWords = Words.Where(predicate ).Select(str => str);foreach (String word in aWords)Console.WriteLine(word);}} 

示例

了解完这些以后,我们来看看它
      不知道童鞋们有没有遇到过这样的问题,在数据读取访问层中数据集合时,发现该方法需要返回的结果中包括对象及其外键对象时也许你会选择用动态对象(动态关键字),不错,这个确实可以解决这个问题,但是有一个弊端,且有动态对象在运行时编译,在编写程序时,它存在一个很不方便的体验,它不能点(.)出它的属性,不免会产生意外的拼写错误或者寻找-复制-粘贴的麻烦。 /p>

那么怎么办呢?我们可以利用Func委托来帮助我们实现。

 public IEnumerable GetAllUser<TResult>(Func itemFactory){var results = from u in Userjoin p in Person on u.Id equals p.uIdselect new { User = u, Person = p } ;IList resultItems = new List();foreach (var item in results.ToList()){resultItems.Add(itemFactory(item.User, item.Person)); }return resultItems;} 

数据访问层

 var query = userDao.GetAllUser((u, p) =>{return new { u.Id , u.LoginName, pId = p.Id, p.Name };}); 

表示层调取

/**************************************** **

C# 有返回类型的内置委托—Func

2.1 初识Func

MSDN给出的定义: <

此委托的定义如下:

public delegate TResult Func(T arg)

(1)in T :此委托封装方法的参数类型。

(2)out TResult :此委托封装方法的返回值类型。

可以使用此委托表示一种能以参数的形式传递的方法,而不是用显式声明自定义委托。封装的方法必须与此委托定义的方法签名相对应。既然如此,封装的方法必须有一个通过值传递给它的参数,并且必须返回值。

2.1.1 没有Func时的使用

 查看代码

< h4>​2.1.2有了Func后的使用

 查看代码

当然,我们还可以借助匿名方法更便捷地使用:

 查看代码

透明可以可以看出,现在使用Func委托时,不一定显式定义一个新的委托抽取抽取方法分配给该委托。

2.2深入Func

2.2.1最先行:爽一下

我们已经知道Func委托是带返回指定值类型的委托,那么我们来看看在实际开发场景的一个场景。还是以刚才那个数据集合PersonList为例,很多时候我们需要对从数据库中读取的数据集合进行二次筛选,接下来我们可以使用List集合的Select方法,我们将一个Func委托实例作为方法参数传递给Select方法,就可以返回一个符合我们指定条件的新数据集合看看

<(1)先来Select方法的定义:

 // // 摘要: // 将序列中的每个元素投影到新表中。 // // 参数: // source: // 一个值序列,要调用序列转换函数。 // // 选择器: // 评估每个元素的转换函数。 //// 类型参数: // TSource: // source 中元素的类型。 // // TResult: // 选择器返回值的类型。 // // 返回结果: // 一个 System.Collections.Generic.IEnumerable ,其元素为对 source 的每个元素调用转换函数的结果。 // // 异常: // System.ArgumentNullException: // source 或 selector 为 null。 public static IEnumerable Select(this IEnumerable source, Func 选择器);

​可以看出, Select方法中的参数采用了Func泛型委托,根据泛型委托的定义TSource和TResult分别代表要确定的数据类型以及要返回的数据类型。

<<(2)接下来看看如何在程序中使用Func委托:

首先定义一个与源数据类型不同的新数据类型作为返回值类型:

 public class LitePerson { public string Name { get; }放; } }

:①标准定义版:

 List personList = GetPersonList( ); IEnumerable litePersonList = personList.Select( new Func ( delegate(Person p) { return new LitePerson() { Name = p.Name }; } ) ); 

【嘻哈简化版:借助编译器提供的自动识别,简化我们的代码

< pre> IEnumerable litePersonList = personList.Select( delegate(Person p) { return new LitePerson() { Name = p.Name }; } );

三绝逼懒人版:借助匿名类和泛型可以大大简化我们的代码

 var liteList = personList.Select(delegate(Person p) { return new { Name = p.Name, AddDate = DateTime.现在 }; });

<(3)调试运行可以得到以下结果:

<2.2.2原理为王:探查一次

<(1)通过Reflector反编译,我们接下来看看编译器帮我们生成的东东:

【(2)查看自动生成的委托和方法的定义:

相信经过上节行动的详细分析,这里大家应该也可以举一反三了解编译器我们到底做了什么事情了,这里我就不再赘述了,后面也不会再赘述这方面的东东(为了节省页面大小)。

当然,和Action类似,.NET基类库为我们也提供了多达16输入参数的Func委托,但是,输出参数却只有1个。

/**************************** *************************

C#委托、Action、Func、lambda表达式

一、委托
注意:在使用委托的时候,
1、在A要委托B的时候,在B中声明一个委托,在A中赋值委托B,当B中的条件触发时,回调A中的方法
举例:当在一个界面中,在点击滑动列表中的某个项目是,在界面中显示该项目详细信息时,可以在滑动列表中创建委托,在界面显示中对滑动列表中的委托进行注册,这样当在点击滑动列表项目的时候,调用委托,传送数据,显示界面数据刷新

1、普通委托不带参数

公共类 TestAction : MonoBehaviour {

public delegate void TestDelegate();
public TestDelegate test;
void Start () {
    test = ShowTest;
    test();
}

void ShowTest() {
    Debug.Log("普通委托。。。");
}

}
< br /> 2、普通委托带参数

public class TestAction : MonoBehaviour {

public delegate void TestDelegate(int temp);
public TestDelegate test;
void Start () {
    test = ShowTest;
    test(2);
}

void ShowTest (int temp) {
    Debug.Log("带参数委托委托。。。" + temp);
}

}

3、C# Action委托,是不带返回值的委托

public class TestAction : MonoBehaviour {

void Start () {< !-- -->
    Action testAction = ShowTest;
    testAction("C# Action 测试!");
}

void ShowTest(string temp) {
    Debug.Log(temp);
}

}

4、C# Func 委托

< p>公共类 TestAction : MonoBehaviour {

void Start () {
    //Func第一个参数是输入类型,第二个返回类型Func
Func testFunc = ShowTest;
    Debug.Log(testFunc("C# Func 测试!"));
}

String ShowTest(string temp) {
    return temp;
}

}

公共类 TestAction : MonoBehaviour {

void Start () {
    //如果是一个类型Func,则表示返回类型为string
    Func testFunc = ShowTest;
    Debug.Log(testFunc());
}

String ShowTest() {
    return "C# Func 测试,单个参数是返回类型!";
}

}

5、lambda表达式
注意:主要用于简化函数,代码看起来简洁明了

public class TestAction : MonoBehaviour {

void Start () {
    //第一个参数是确定参数类型,第二个委托返回类型
    Func testFunc = test => test + 10 + "--返回类型为string";
    Debug.Log(testFunc(2));
}

int ShowTest(int temp) {
    return temp;
}

}

lambda整体写法

public class TestAction : MonoBehaviour {

void Start() {
    Func test = (p, k) => {
        if (p + k == 10)
        {
            返回 true;
        }
        else {
            返回 false;
        }< br />     };
    Debug.Log("lambda表达式,返回值测试 " + test(8,8));
}

}
 

C泛型概念及方式详解原创由知识百科栏目发布,感谢您对的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“C泛型概念及方式详解原创

Copyright © 2012-2023 普诚元亨工作室 版权所有

*本站部分网页素材及相关资源来源互联网,如有侵权请速告知,我们将会在24小时内删除*

Z-BlogPHP 1.7.3 琼ICP备2022020219号