C# core knowledge review - 9. Generics, generic constraints

1. Generics

    Generics implement type parameterization to achieve code reuse.
    Through type parameterization, the same code can operate on multiple types.

    Generics are equivalent to type placeholders.
    When defining a class or method, a substitute is used to represent the variable type.
    When the class or method is actually used, the type is specified.

    Basic syntax for generic classes and generic interfaces
    :
    class class name <generic placeholder letter>
    interface interface name <generic placeholder letter>

public class test : MonoBehaviour
{
    private void Start()
    {
        TestClass<int> testClass = new TestClass<int>();
        Debug.Log(testClass.value);
        TestClass2<int,string,bool> testclass2 = new TestClass2<int,string,bool>();
        Debug.Log(testclass2.value);
        
    }
}

class TestClass<T>
{
    public T value;
}
class TestClass2<T, K, M>
{
    public K key;
    public M value;
    public T Value { get; set; }
}
public interface TestInterface<T>
{
     T Value { get; set; }
}
class TestGetInter : TestInterface<int>
{
    public int Value { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}

    Basic syntax of generic functions
    : function name <generic placeholder letter> (parameter list)

    Note: There can be multiple generic placeholder letters, separated by commas

/// <summary>
    /// 普通类里面的泛型方法
    /// </summary>
    public void testFun<T>(T value)
    {
        Debug.Log(value);
    }
    public void testFunc<T>()
    {
        //用泛型做逻辑处理
        T t = default(T);
    }
    public T testFun<T>()
    {
        return default(T);
    }

    private void Start()
    {
        testFun<string>("12");        
    }
/// <summary>
/// 泛型类中的泛型方法
/// </summary>
public class test : MonoBehaviour
{    
    private void Start()
    {
        Test2<int> test = new Test2<int>();
        //被限定了类型。函数只能传int
        test.Func(1);
        //Func2是真正的泛型方法
        test.Func2("123");
        test.Func2(false);
    }
}
class Test2<T>
{
    public T value;
    /// <summary>
    /// 这个不叫泛型方法,T在类已经定性了。
    /// </summary>
    public void Func<T>(T t) { Debug.Log(t); }
    /// <summary>
    /// 这个才是泛型方法
    /// </summary>
    public void Func2<K>(K k) { }
}

2. Generic constraints

Let the generic type have certain restrictions.
Keyword: where
There are 6 types of generic constraints
1. Value type where generic letter: struct
2. Reference type where generic letter: class
3. There is a parameterless public constructor where generic Type letter: new()
4. A certain class itself or its derived class where generic letter: class name
5. Derived type of an interface where generic letter: interface name
6. Another generic type itself or a derived type where generic letter: another generic letter

/// <summary>
/// 泛型类中的泛型方法
/// </summary>
public class test : MonoBehaviour
{    
    private void Start()
    {
        Test2<int> t1= new Test2<int>();                        值类型
        t1.TestFunc<float> (1.3f);

        Test3<System.Random> t2 = new Test3<System.Random>();   引用类型
        t2.TestFunc<int[]>(new int[5]);

        //<Get2>必须是公共的无参数构造函数的非抽象类型
        Test4<Get2> t3 = new Test4<Get2>();                     无参构造函数

        Test5<Get2> t5 = new Test5<Get2>();                     类约束

        Test6<IGet3> t6 = new Test6<IGet3>();                   接口约束

        Test7<IGet4,IGet3> t7 = new Test7<IGet4,IGet3>();       另一个泛型约束
        //IGet4继承于IGet3
    }
}
class Get2
{
    public Get2(int a) { }
    public Get2() { }
}
interface IGet3
{
}
interface IGet4 : IGet3
{
}
/// <summary>
/// 值类型约束
/// </summary>
class Test2<T> where T : struct
{
    public T value;
    public void TestFunc<K>(K k) where K : struct { }
}
/// <summary>
/// 引用类型约束
/// </summary>
class Test3<T> where T : class
{
    public T value;
    public void TestFunc<K>(K k) where K : class { }
}
/// <summary>
/// 无参构造函数
/// </summary>
class Test4<T> where T : new()
{
    public T value;
    public void TestFunc<K>(K k) where K : struct{ }
}
/// <summary>
/// 类约束
/// </summary>
class Test5<T> where T : Get2  //某个类或者其派生类
{
    public T value;
    public void TestFunc<K>(K k) where K : struct { }
}
/// <summary>
/// 接口约束
/// </summary>
class Test6<T> where T : IGet3  //某个接口或者其派生类/派生接口
{
    public T value;
    public void TestFunc<K>(K k) where K : struct { }
}
/// <summary>
/// 另一个泛型约束
/// </summary>
class Test7<T,U> where T : U  //另一个泛型本身或者派生类
{
    public T value;
    public void TestFunc<K>(K k) where K : struct { }
}

Use combinations of constraints:

//new()要放在后面
class Test3<T> where T : class,new()
{
    public T value;
    public void TestFunc<K>(K k) where K : class { }
}

Multiple generics have constraints:

class Test2<T,M> where T : struct where M : struct
{
    public T value;
    public void TestFunc<K>(K k) where K : struct { }
}

Guess you like

Origin blog.csdn.net/qq_29296473/article/details/131536896