Unity basic learning sixteen, C# advanced attributes: generic (Generic), anonymous methods (Anonymous methods)

1. C# Generics

Generics  allow you to delay writing the specification of the data type of a programming element in a class or method until it is time to actually use it in the program. In other words, generics allow you to write a class or method that works with any data type.

You can write the specification of a class or method with substitution parameters of data types. When the compiler encounters a constructor of a class or a function call to a method, it generates code to handle the specified data type. The following simple example will help you understand the concept:

using System;
using System.Collections.Generic;

namespace GenericApplication
{
    public class MyGenericArray<T>
    {
        private T[] array;
        public MyGenericArray(int size)
        {
            array = new T[size + 1];
        }
        public T getItem(int index)
        {
            return array[index];
        }
        public void setItem(int index, T value)
        {
            array[index] = value;
        }
    }
           
    class Tester
    {
        static void Main(string[] args)
        {
            // 声明一个整型数组
            MyGenericArray<int> intArray = new MyGenericArray<int>(5);
            // 设置值
            for (int c = 0; c < 5; c++)
            {
                intArray.setItem(c, c*5);
            }
            // 获取值
            for (int c = 0; c < 5; c++)
            {
                Console.Write(intArray.getItem(c) + " ");
            }
            Console.WriteLine();
            // 声明一个字符数组
            MyGenericArray<char> charArray = new MyGenericArray<char>(5);
            // 设置值
            for (int c = 0; c < 5; c++)
            {
                charArray.setItem(c, (char)(c+97));
            }
            // 获取值
            for (int c = 0; c < 5; c++)
            {
                Console.Write(charArray.getItem(c) + " ");
            }
            Console.WriteLine();
            Console.ReadKey();
        }
    }
}
0 5 10 15 20
a b c d e

1.1 Generic features

The use of generics is a technique to enhance program functionality, specifically in the following aspects:

  • It helps you maximize code reuse, protect type safety, and improve performance.
  • You can create generic collection classes. The .NET Framework class library   includes some new generic collection classes in the System.Collections.Generic namespace. You can use these generic collection classes in place of   the collection classes in System.Collections .
  • You can create your own generic interfaces, generic classes, generic methods, generic events, and generic delegates.
  • You can constrain a generic class to access methods of a specific data type.
  • Information about the types used in generic data types can be obtained at runtime by using reflection.

1.2 Generic method

In the above example, we have used generic classes and we can declare generic methods with type parameters. The following program illustrates this concept:

using System;
using System.Collections.Generic;

namespace GenericMethodAppl
{
    class Program
    {
        static void Swap<T>(ref T lhs, ref T rhs)
        {
            T temp;
            temp = lhs;
            lhs = rhs;
            rhs = temp;
        }
        static void Main(string[] args)
        {
            int a, b;
            char c, d;
            a = 10;
            b = 20;
            c = 'I';
            d = 'V';

            // 在交换之前显示值
            Console.WriteLine("Int values before calling swap:");
            Console.WriteLine("a = {0}, b = {1}", a, b);
            Console.WriteLine("Char values before calling swap:");
            Console.WriteLine("c = {0}, d = {1}", c, d);

            // 调用 swap
            Swap<int>(ref a, ref b);
            Swap<char>(ref c, ref d);

            // 在交换之后显示值
            Console.WriteLine("Int values after calling swap:");
            Console.WriteLine("a = {0}, b = {1}", a, b);
            Console.WriteLine("Char values after calling swap:");
            Console.WriteLine("c = {0}, d = {1}", c, d);
            Console.ReadKey();
        }
    }
}
Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I

1.3 Generic delegation

You can define generic delegates with type parameters. For example:

delegate T NumberChanger<T>(T n);
using System;
using System.Collections.Generic;

delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl
{
    class TestDelegate
    {
        static int num = 10;
        public static int AddNum(int p)
        {
            num += p;
            return num;
        }

        public static int MultNum(int q)
        {
            num *= q;
            return num;
        }
        public static int getNum()
        {
            return num;
        }

        static void Main(string[] args)
        {
            // 创建委托实例
            NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
            NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);
            // 使用委托对象调用方法
            nc1(25);
            Console.WriteLine("Value of Num: {0}", getNum());
            nc2(5);
            Console.WriteLine("Value of Num: {0}", getNum());
            Console.ReadKey();
        }
    }
}
Value of Num: 35
Value of Num: 175

When declaring a generic method/generic class, certain constraints can be added to the generic to meet some of our specific conditions.

using System;
using System.Web.Caching;

namespace Demo.CacheManager
{
   public class CacheHelper<T> where T:new()
   {
      
   }
}

Generic qualification:

  •  T: Struct (type parameter must be a value type. Any value type except Nullable can be specified)
  •  T: Class (the type parameter must be a reference type, including any class, interface, delegate, or array type)
  •  T: new() (The type parameter must have a parameterless public constructor. When used with other constraints the new() constraint must be specified last)
  •  T:<base class name> type parameter must be of or derived from the specified base class
  •  T:<interface name> type parameter must be the specified interface or implement the specified interface. Multiple interface constraints can be specified. Constraint interfaces can also be generic.
  •  T:U

2.c# anonymous method

A delegate is used to reference a method with the same label as it. In other words, you can use the delegate object to call methods that can be referenced by the delegate.

Anonymous methods  provide a technique for passing blocks of code as delegate parameters. An anonymous method is a method that has no name but only a body.

In anonymous methods you don't need to specify the return type, it is inferred from the return statement within the method body.

2.1 Syntax for writing anonymous methods 

 Anonymous methods are declared by creating a delegate instance using  the delegate keyword. For example:

delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x)
{
    Console.WriteLine("Anonymous Method: {0}", x);
};

The code block Console.WriteLine("Anonymous Method: {0}", x); is the body of the anonymous method.

Delegates can be invoked through anonymous methods or through named methods, that is, by passing method parameters to the delegate object.

Note:  A ; is required after the body of the anonymous method .

For example:

nc(10);
using System;

delegate void NumberChanger(int n);
namespace DelegateAppl
{
    class TestDelegate
    {
        static int num = 10;
        public static void AddNum(int p)
        {
            num += p;
            Console.WriteLine("Named Method: {0}", num);
        }

        public static void MultNum(int q)
        {
            num *= q;
            Console.WriteLine("Named Method: {0}", num);
        }

        static void Main(string[] args)
        {
            // 使用匿名方法创建委托实例
            NumberChanger nc = delegate(int x)
            {
               Console.WriteLine("Anonymous Method: {0}", x);
            };
           
            // 使用匿名方法调用委托
            nc(10);

            // 使用命名方法实例化委托
            nc =  new NumberChanger(AddNum);
           
            // 使用命名方法调用委托
            nc(5);

            // 使用另一个命名方法实例化委托
            nc =  new NumberChanger(MultNum);
           
            // 使用命名方法调用委托
            nc(2);
            Console.ReadKey();
        }
    }
}
Anonymous Method: 10
Named Method: 15
Named Method: 30

Guess you like

Origin blog.csdn.net/u013617851/article/details/124436860