• 【C#食谱】【面食】菜单6:泛型约束


    问题:

    你希望你的泛型类型在创建的时候必须有一个支持某个接口(比如IDisposable接口)成员的类型参数。

    解决方法:

    使用约束去强制泛型的类型参数实现某一个或多个特定的接口。

        public class DisposableList<T> : IList<T>   
            
    where T : IDisposable
            
    {
                
    private List<T> _items = new List<T>();

                
    // Private method that will dispose of items in the list
                private void Delete(T item)
                
    {
                    item.Dispose();
                }

            }

    这个DisposableList类只允许实现了IDisposable接口的对象作为参数传递给它。那是因为,每次你从DisposableList对象中删除一个对象时,都要调用Dispose方法。这就使得你可以轻松管理DisposableList中的对象。

    下面的代码就运用了DisposableList对象:

        public static void TestDisposableListCls() 
        
    {    
            DisposableList
    <StreamReader> dl = new DisposableList<StreamReader>();

            
    // Create a few test objects.
            StreamReader tr1 = new StreamReader("c:\\boot.ini");
            StreamReader tr2 
    = new StreamReader("c:\\autoexec.bat");
            StreamReader tr3 
    = new StreamReader("c:\\config.sys");

            
    // Add the test object to the DisposableList.
            dl.Add(tr1);
            dl.Insert(
    0, tr2);
            dl.Add(tr3);

            
    foreach(StreamReader sr in dl)
            
    {
                Console.WriteLine(
    "sr.ReadLine() == " + sr.ReadLine());
            }


            
    // Call Dispose before any of the disposable objects are
            
    // removed from the DisposableList.
            dl.RemoveAt(0);
            dl.Remove(tr1);
            dl.Clear();
        }

    讨论:

    Where关键字被用来约束类型参数只能接受那些满足给定约束的参数。比如,DisposableList有一个约束就是任何类型参数T必须实现IDisposable接口:

        public class DisposableList<T> : IList<T>
            
    where T : IDisposable

    这意味着,下面的代码将编译成功:

        DisposableList<StreamReader> dl = new DisposableList<StreamReader>();

    但这个就不行了:

        DisposableList<string> dl = new DisposableList<string>();

    这是因为string并没有实现IDisposable接口,而StreamReader实现了。

    除了要求一个或多个接口被实现,其他对于类型参数的约束也是被允许的。你可以要求一个类型参数必须继承自一个特定的基类,比如Textreader类:

        public class DisposableList<T> : IList<T>
            
    where T : System.IO.TextReader, IDisposable

    你也可以约束这个类型参数只能是值类型或者只能是引用类型。下面声明的类的约束是其只能使用值类型:

        public class DisposableList<T> : IList<T>
            
    where T : struct

    而这个是只能使用引用类型:

        public class DisposableList<T> : IList<T>
            
    where T : class

    除此之外,你也可以要求任何类型参数去实现一个公共的默认构造函数:

        public class DisposableList<T> : IList<T>
            
    where T : IDisposable, new()

    使用约束使得你可以编写的泛型只能接受那些更具体的有用的参数类型。如果在这个示例中,IDsiposable约束被省略,那么一个编译时错误将会发生。这是因为,不是所有的类型它都可以被用作是实现了IDisposable接口的DisposableList类的参数的。如果你忽略这个编译时检查,一个DisposableList对象也许会包含那些并没有一个公共的无参数的Dispose方法的对象。在这种情况下,一个运行时异常将会发生。泛型和约束在一定程度上要求严格的参数类型检查,这使你在编译时就可以发现这些问题,而不是运行时。

  • 相关阅读:
    深入NET框架
    解决idea中maven的pom文件不会自动下载jar包问题
    JSP中的作用域
    转发与重定向
    JSP内置对象
    JNDI与连接池
    文件上传
    七大设计原则
    第六章 初始继承和多态
    C#和.NET框架
  • 原文地址:https://www.cnblogs.com/adaiye/p/constraints.html
Copyright © 2020-2023  润新知