泛型(三)

可验证性和约束(Verifiability and Constraints)
约束
的作用是限制能指定成泛型实参的类型数量。通过限制类型的数量,可以对那些类型执行更多的操作。(A constraint is a way to limit the number of types that can be specified for a generic argument. Limiting the number of types allows you to do more with those types.)

1、The CLR doesn’t allow overloading based on type parameter names or constraints; you can overload types or methods based only on arity. 

2、Whenoverriding a virtual generic method, the overriding method must specify the same num-ber of type parameters, and these type parameters will inherit the constraints specified on them by the base class’s method. In fact, the overriding method is not allowed to specify any constraints on its type parameters at all. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyGenerics4
{
    internal class Base 
    { 
        public virtual void M<T1, T2>() 
            where T1 : struct 
            where T2 : class 
            { } 
    } 

    internal sealed class Derived : Base
    { 
        public override void M<T3, T4>() 
            where T3 : EventArgs // Error 
            where T4 : class // Error 
            { } 
    }

    class Program
    {
        private static bool MethodTakingAnyType<T>(T o)
        {
            T tmp = o;
            Console.WriteLine(o.ToString());
            bool b = tmp.Equals(o);
            return b;
        }

        public static T Min<T>(T o1, T o2) where T : IComparable<T>
        {
            if (o1.CompareTo(o2) < 0)
                return o1;

            return o2;
        }

        private static void CallMin()
        {
            Object o1 = "Jeff", o2 = "Richter";
            Object oMin = Min<Object>(o1, o2); // Error CS0311
        }

        // It is OK to define the following types: 
        internal sealed class AType { }
        internal sealed class AType<T> { }
        internal sealed class AType<T1, T2> { }
        // Error: conflicts with AType<T> that has no constraints 
        internal sealed class AType<T> where T : IComparable<T> { }
        // Error: conflicts with AType<T1, T2>
        internal sealed class AType<T3, T4> { }
        internal sealed class AnotherType
        {
            // It is OK to define the following methods: 
            private static void M() { }
            private static void M<T>() { }
            private static void M<T1, T2>() { }
            // Error: conflicts with M<T> that has no constraints 
            private static void M<T>() where T : IComparable<T> { }
            // Error: conflicts with M<T1, T2>
            private static void M<T3, T4>() { }
        }

        static void Main(string[] args)
        {
        }
    }
}

1、首要约束(Primary Constraints)
A typeparameter can specify zero primary constraints or one primary constraint. A primary constraint can be a reference type that identifies a class that is not sealed.
有两个特殊的首要约束:class、struct
 1)The class constraint promises the compiler that a specified type argument will be a reference type. Any class type, interface type, del-egate type, or array type satisfies this constraint.

2)The struct constraint promises the compiler that a specified type argument will be a value type. Any value type, including enumerations, satisfies this constraint. 

    internal sealed class PrimaryConstraintOfClass<T> where T : class 
    { 
        public void M() 
        { 
            T temp = null;// Allowed because T must be a reference type 
        } 
    }


    internal sealed class PrimaryConstraintOfStruct<T> where T : struct 
    { 
        public static T Factory() 
        { 
        // Allowed because all value types implicitly 
        // have a public, parameterless constructor 
            return new T(); 
        } 
    }

2、次要约束(Secondary Constraints)

1)接口类型约束
A type parameter can specify zero or more secondary constraints where a secondary constraint rep-resents an interface type. 
2)类型参数约束(裸露类型约束)
It allows a generic type or method to indicate that there must be a relationship between specified type arguments.

<pre name="code" class="csharp">         private static List<TBase> ConvertIList<T, TBase>(IList<T> list) 
            where T : TBase
        { 
            List<TBase> baseList = new List<TBase>(list.Count); 
            for (Int32 index = 0; index < list.Count; index++)
            { 
                baseList.Add(list[index]); 
            } 
            return baseList; 
        }

        private static void CallingConvertIList()
        { 
            // Construct and initialize a List<String> (which implements IList<String>) 
            IList<String> ls = new List<String>(); 
            ls.Add("A String"); 
            // Convert the IList<String> to an IList<Object>
            IList<Object> lo = ConvertIList<String, Object>(ls); 
            // Convert the IList<String> to an IList<IComparable>
            IList<IComparable> lc = ConvertIList<String, IComparable>(ls); 
            // Convert the IList<String> to an IList<IComparable<String>>
            IList<IComparable<String>> lcs = 
            ConvertIList<String, IComparable<String>>(ls); 
            // Convert the IList<String> to an IList<String>
            IList<String> ls2 = ConvertIList<String, String>(ls); 
            // Convert the IList<String> to an IList<Exception>
            IList<Exception> le = ConvertIList<String, Exception>(ls);// Error 
        }

 
 

3、构造器约束(Constructor Constraints)
Atype parameter can specify zero constructor constraints or one constructor constraint. When speci-fying a constructor constraint, you are promising the compiler that a specified type argument will be 
a non-abstract type that implements a public, parameterless constructor.
    internal sealed class ConstructorConstraint<T> where T : new() 
    { 
        public static T Factory()
        { 
            // Allowed because all value types implicitly 
            // have a public, parameterless constructor and because 
            // the constraint requires that any specified reference 
            // type also have a public, parameterless constructor 
            return new T(); 
        } 
    }

其他可验证性问题
1、强转一个泛型类型变量
2、设置一个泛型类型变量为一个默认值 
3、泛型类型变量与null比较
4、两个相同泛型类型的变量比较
5、使用泛型类型变量作为操作数

你可能感兴趣的:(泛型(三))