精华内容
下载资源
问答
  • c#泛型接口
    千次阅读
    2018-07-31 17:01:11

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

    namespace GenericInterface1
    {
        class Program
        {
            public interface MyGenericInterface<T>
                //T 是类型参数。在实例化泛型的时候,可以使用约束对参数类型的种类进行限制。
                //定义一个泛型接口,泛型接口的声明与普通接口的声明的唯一区别是增加了一个T
                //泛型类型声明所实现的接口必须对所有可能的构造类型都保持唯一。
                //否则就无法确定该为某些构造类型调用哪个方法。
            {
                T Create();//接口调用Create方法。
            } 
            //实现上面泛型接口的泛型类
            //派生约束where T:TI(T要继承TI)
            //构造函数约束where T:new(可以实例化)
            public class Factory<T,TI>:MyGenericInterface<TI> where T : TI, new()
            {
                //public TI Create()
                //{
                //    throw new NotImplementedException();
                //}

                public TI  Create()
                {
                    return new T();
                }
            }
                
            static void Main(string[] args)
            {
                MyGenericInterface<System.ComponentModel.IListSource> facktory = 
                new Factory<System.Data.DataTable, System.ComponentModel.IListSource>();
                //输出指定泛型的类型。
                Console.WriteLine(facktory.Create().GetType().ToString());
                Console.ReadLine();
            }
        }
    }
     

    更多相关内容
  • 1, 泛型接口的协变 如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。 泛型接口的抗变 如果泛型类型用in关键字标注,泛型接口就是抗变的。这样,接口只能把泛型类型T用作其方法的输入...
  • C#泛型接口实例

    2014-02-25 15:45:08
    C# 实现泛型接口
  • C#泛型接口

    2016-09-08 16:12:00
    对于泛型类,使用泛型接口十分可取,例如使用 IComparable&lt;T&gt; 而不使用 IComparable,这样可以避免值类型的装箱和取消装箱操作。.NET Framework 2.0 类库定义了若干新的泛型接口,以用于 System....

      为泛型集合类或表示集合中项的泛型类定义接口通常很有用。对于泛型类,使用泛型接口十分可取,例如使用 IComparable<T> 而不使用 IComparable,这样可以避免值类型的装箱和取消装箱操作。.NET Framework 2.0 类库定义了若干新的泛型接口,以用于 System.Collections.Generic 命名空间中新的集合类。

    将接口指定为类型参数的约束时,只能使用实现此接口的类型。下面的代码示例显示从 GenericList<T> 类派生的 SortedList<T> 类。SortedList<T> 添加了约束 where T : IComparable<T>。这将使SortedList<T> 中的 BubbleSort 方法能够对列表元素使用泛型 CompareTo 方法。在此示例中,列表元素为简单类,即实现 IComparable<Person> 的 Person

    C#
    //Type parameter T in angle brackets.
    public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
    {
    protected Node head;
    protected Node current = null;

    // Nested class is also generic on T
    protected class Node
    {
    public Node next;
    private T data; //T as private member datatype

    public Node(T t) //T used in non-generic constructor
    {
    next = null;
    data = t;
    }

    public Node Next
    {
    get { return next; }
    set { next = value; }
    }

    public T Data //T as return type of property
    {
    get { return data; }
    set { data = value; }
    }
    }

    public GenericList() //constructor
    {
    head = null;
    }

    public void AddHead(T t) //T as method parameter type
    {
    Node n = new Node(t);
    n.Next = head;
    head = n;
    }

    // Implementation of the iterator
    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
    {
    Node current = head;
    while (current != null)
    {
    yield return current.Data;
    current = current.Next;
    }
    }

    // IEnumerable<T> inherits from IEnumerable, therefore this class
    // must implement both the generic and non-generic versions of
    // GetEnumerator. In most cases, the non-generic method can
    // simply call the generic method.
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
    return GetEnumerator();
    }
    }

    public class SortedList<T> : GenericList<T> where T : System.IComparable<T>
    {
    // A simple, unoptimized sort algorithm that
    // orders list elements from lowest to highest:

    public void BubbleSort()
    {
    if (null == head || null == head.Next)
    {
    return;
    }
    bool swapped;

    do
    {
    Node previous = null;
    Node current = head;
    swapped = false;

    while (current.next != null)
    {
    // Because we need to call this method, the SortedList
    // class is constrained on IEnumerable<T>
    if (current.Data.CompareTo(current.next.Data) > 0)
    {
    Node tmp = current.next;
    current.next = current.next.next;
    tmp.next = current;

    if (previous == null)
    {
    head = tmp;
    }
    else
    {
    previous.next = tmp;
    }
    previous = tmp;
    swapped = true;
    }
    else
    {
    previous = current;
    current = current.next;
    }
    }
    } while (swapped);
    }
    }

    // A simple class that implements IComparable<T> using itself as the
    // type argument. This is a common design pattern in objects that
    // are stored in generic lists.
    public class Person : System.IComparable<Person>
    {
    string name;
    int age;

    public Person(string s, int i)
    {
    name = s;
    age = i;
    }

    // This will cause list elements to be sorted on age values.
    public int CompareTo(Person p)
    {
    return age - p.age;
    }

    public override string ToString()
    {
    return name + ":" + age;
    }

    // Must implement Equals.
    public bool Equals(Person p)
    {
    return (this.age == p.age);
    }
    }

    class Program
    {
    static void Main()
    {
    //Declare and instantiate a new generic SortedList class.
    //Person is the type argument.
    SortedList<Person> list = new SortedList<Person>();

    //Create name and age values to initialize Person objects.
    string[] names = new string[]
    {
    "Franscoise",
    "Bill",
    "Li",
    "Sandra",
    "Gunnar",
    "Alok",
    "Hiroyuki",
    "Maria",
    "Alessandro",
    "Raul"
    };

    int[] ages = new int[] { 45, 19, 28, 23, 18, 9, 108, 72, 30, 35 };

    //Populate the list.
    for (int x = 0; x < 10; x++)
    {
    list.AddHead(new Person(names[x], ages[x]));
    }

    //Print out unsorted list.
    foreach (Person p in list)
    {
    System.Console.WriteLine(p.ToString());
    }
    System.Console.WriteLine("Done with unsorted list");

    //Sort the list.
    list.BubbleSort();

    //Print out sorted list.
    foreach (Person p in list)
    {
    System.Console.WriteLine(p.ToString());
    }
    System.Console.WriteLine("Done with sorted list");
    }
    }

    可将多重接口指定为单个类型上的约束,如下所示:

    C#
    class Stack<T> where T : System.IComparable<T>, IEnumerable<T>
    {
    }

    一个接口可定义多个类型参数,如下所示:

    interface IDictionary<K, V>
    {
    }

    类之间的继承规则同样适用于接口:

    C#
    interface IMonth<T> { }

    interface IJanuary : IMonth<int> { } //No error
    interface IFebruary<T> : IMonth<int> { } //No error
    interface IMarch<T> : IMonth<T> { } //No error
    //interface IApril<T> : IMonth<T, U> {} //Error

    如果泛型接口为逆变的,即仅使用其类型参数作为返回值,则此泛型接口可以从非泛型接口继承。在 .NET Framework 类库中,IEnumerable<T> 从 IEnumerable 继承,因为 IEnumerable<T> 仅在 GetEnumerator 的返回值和当前属性 getter 中使用 T。

    具体类可以实现已关闭的构造接口,如下所示:

    C#
    interface IBaseInterface<T> { }

    class SampleClass : IBaseInterface<string> { }

    只要类参数列表提供了接口必需的所有参数,泛型类便可以实现泛型接口或已关闭的构造接口,如下所示:

    C#
    interface IBaseInterface1<T> { }
    interface IBaseInterface2<T, U> { }

    class SampleClass1<T> : IBaseInterface1<T> { } //No error
    class SampleClass2<T> : IBaseInterface2<T, string> { } //No error

    对于泛型类、泛型结构或泛型接口中的方法,控制方法重载的规则相同。

    展开全文
  • 泛型类、泛型方法、泛型接口、泛型委托 泛型类、泛型方法、泛型接口、泛型委托
  • 一、协变和逆变是什么? 先从字面上理解 协变(Covariance)、逆变(Contravariance)。co- 是英文中表示“协同”、“合作”的前缀。协变 的字面意思就是 “与变化的方向相同...C# 中对于对象(即对象引用),仅存在一种隐

    一、协变和逆变是什么?
    先从字面上理解 协变(Covariance)、逆变(Contravariance)。

    co- 是英文中表示“协同”、“合作”的前缀。协变 的字面意思就是 “与变化的方向相同”。
    contra- 是英文中表示“相反”的前缀,逆变 的字面意思就是是 “与变化方向相反”。
    那么问题来了,挖掘机技术哪家强?这里的 变化方向 指的是什么?

    C# 中对于对象(即对象引用),仅存在一种隐式类型转换,即 子类型的对象引用到父类型的对象引用的转换。这里的变化指的就是这种 子->父 的类型转换。

    object o = "hello";
    //string (子类)类型的引用转换为 object (父类)类型的引用

    协变与逆变虽然从名字上看是两个完全相反的转换,但其实只是“子类型引用到父类型引用”这一过程在函数中使用的 两个不同阶段 而已,接下来将详细说明这点。

    二、使用函数的不同阶段发生的类型转换
    假设有一函数,接收 object 类型的参数,输出 string 类型的返回值:

    string Method(object o)
    {
        return "abc";
    }

    那么在Main函数中我们可以这样调用它:

    string s = "abc";
    object o = Method(s);

    注意,这里发生了两次隐式类型转换:

    在向函数输入时,参数 s 由 string 类型转换为 object 类型
    在函数输出(返回)时,返回值 由 string 类型转换为 object 类型
    我们这里可以看作是函数签名可发生变换(不论函数的内容,不影响结果):

    string Method(object o) 可变换为 string Method(string o)
    string Method(string o) 可变换为 object Method(string o)
    也就是说,在函数输入时,函数的 输入类型 可由 object 变换为 string,父->子
    在函数输出时,函数的 输出类型 可由string变换为object,子->父

    三、理解泛型接口中的 in、out参数
    没有指定in、out的情况
    假设有一泛型接口,并且有一个类实现了此接口:

    interface IDemo<T>
    {
        T Method(T value);
    }
    public class Demo : IDemo<string>
    {
        //实现接口 IDemo<string>
    
        public string Method(string value)
        {
            return value;
        }
    }

    在Main函数中这样写:

    IDemo<string> demoStr = new Demo();
    IDemo<object> demoObj = demoStr;
    上面的这段代码中的第二行包含了一个假设:
    
    IDemo<string> 类型能够隐式转换为 IDemo<object> 类型
    
    这乍看上去就像“子类型引用转换为父类型引用” 一样,然而很遗憾,他们并不相同。假如可以进行隐式类型转换,那就意味着:
    
    string Method(string value) 能转换为 object Method(object value)
    
    从上一节中我们知道,在函数这输入和输出阶段,其类型可变化方向是不同的。所以在C#中,要想应用泛型接口类型的隐式转换,需要讨论“输入”和“输出”两种情况。
    
    接口仅用于输出的情况,协变
    interface IDemo<out T>
    {
        //仅将类型 T 用于输出
        T Method(object value);
    }
    
    public class Demo : IDemo<string>
    {
        //实现接口
        public string Method (object value)
        {
            //别忘了类型转换!
            return value.ToString();
        }
    }    
    在Main函数中这样写:
    
    IDemo<string> demoStr = new Demo();
    IDemo<object> demoObj = demoStr;
    可将 string Method (object value) 转换为 object Method (object value)
    即可将 IDemo<string> 类型转换为 IDemo<object> 类型。
    仅从泛型的类型上看,这是 “子->父” 的转换,与第一节中提到的转换方向相同,称之为“协变”。
    
    接口仅用于输入的情况,逆变
    同理我们可以给 T 加上 in 参数:
    interface IDemo<in T>
    {
        //仅将类型 T 用于输入
        string Method(T value);
    }
    
    public class Demo : IDemo<object>
    {
        //实现接口
        public string Method (object value)
        {
            return value.ToString();
        }
    }    
    在Main函数中这样写:
    
    IDemo<object> demoObj = new Demo();
    IDemo<string> demoStr = demoObj;
    这里可将 string Method (object value) 转换为 string Method (string value)
    即可将 IDemo<object> 类型转换为 IDemo<string> 类型。
    仅从泛型的类型上看,这是 “父->子” 的转换,与第一节中提到的转换方向相反,称之为“逆变”,有时也译作“抗变”或“反变”。

    四、总结
    以上只讨论了协变与逆变在方法中的情况,其实在属性中情况也相类似,不再说明。

    可能大家也发现了,所谓“协”与“逆”都是只是一种表象,其内在本质为同一过程。

    “协变”与“逆变”中的“协”与“逆”表示泛型接口在将类型参数仅用于输入或输出的情况下,其类型参数的隐式转换所遵循的规律。
    协变
    当泛型接口类型仅用于输出(使用关键词 out),其类型参数隐式转换所遵循的规律与对象引用的类型转换规律相同,称之为“协变”
    逆变
    当泛型接口类型仅用于输入(使用关键词 in),其类型参数隐式转换所遵循的规律与对象引用的类型转换规律相反,称之为“逆变”、“抗变”或“反变”。

    展开全文
  • 主要介绍了C#中的泛型类与泛型接口,对泛型的支持是C#语言的重要特性,需要的朋友可以参考下
  • C# 泛型 接口约束

    千次阅读 2015-05-06 23:39:46
    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace interfaceConstraint { interface IPhoneNumber { String Name { get;


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace interfaceConstraint
    {
        interface IPhoneNumber
        {
            String Name
            {
                get;
                set;
            }
    
            string Number
            {
                get;
                set;
            }
        }
    
        class Friend : IPhoneNumber
        {
            string name;
            string number;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public string Number
            {
                get { return name; }
                set { name = value; }
            }
    
            public Friend(string name, string number)
            {
                this.name = name;
                this.number = number;
            }
        }
    
        class Supplier : IPhoneNumber
        { 
            string name;
            string number;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public string Number
            {
                get { return name; }
                set { name = value; }
            }
    
            public Supplier(string name, string number)
            {
                this.name = name;
                this.number = number;
            }
        }
    
        class others
        { }
    
    
        class PhoneList<T> where T : IPhoneNumber
        {
            T[] phList;
            int end;
            public PhoneList()
            { 
                phList=new T[10];
                end = 0;
            }
    
            public bool Add(T newNumber)
            {
                if (end == 10)
                    return false;
                phList[end] = newNumber;
                end++;
                return true;
            }
    
            public void findByName(string name)
            {
                for (int i = 0; i < end; i++)
                    if (phList[i].Name == name)
                    {
                        Console.WriteLine("姓名是{0}的电话号码是{1}",name,phList[i].Number);
                        return;
                    }
                Console.WriteLine("没有找到");
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                PhoneList<Friend> phList1 = new PhoneList<Friend>();
    
                phList1.Add(new Friend("zhangsan", "123")); 
                phList1.Add(new Friend("lisi", "234"));
                phList1.findByName("lisi");
                Console.WriteLine("============");
    
                PhoneList<Supplier> phList2 = new PhoneList<Supplier>();
    
                phList1.Add(new Friend("zhangsan1", "123"));
                phList1.Add(new Friend("lisi1", "234"));
                phList1.findByName("lisi11");
    
                Console.ReadLine();
            }
        }
    }
    


    展开全文
  • c#泛型类、泛型方法、泛型接口、泛型委托
  • C# 关于自定义泛型类,泛型方法,泛型接口实现算法重用>
  • C# 泛型接口(1)

    2019-02-14 10:50:59
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Examplew { interface IMyIfc&lt;T&gt; // Gen...
  • C#泛型约束

    千次阅读 2022-05-24 20:08:10
    泛型的六种约束
  • 摘要:C#源码,文件操作,TInterface,创建泛型接口 C#创建或使用一个 TInterface泛型接口的源码实例,大致实现的思路:创建一个泛型接口public interface IGenericInterface,接口中调用CreateInstance方法,实现上面...
  • c#: 泛型接口、泛型方法

    万次阅读 2018-01-03 16:29:17
    泛型可以自定义泛型接口、泛型类、泛型方法、泛型事件、泛型委托。 1>自定义泛型接口 和普通接口一样,一个泛型接口通常也是与某些对象相关的约定规程。泛型接口的声明如下: interface [接口名] { [接口体] } 在c#...
  • c# 接口泛型

    2021-05-22 10:37:08
    接口(关键字 interface) 1、接口的概念 接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。 接口定义了属性、方法和事件,这些都是...
  • 1 定义泛型接口 前面介绍了几个泛型接口,它们都位于Systems.Collections.Generic名称空间中,例如,上一个示例中使用的IEnumerable<T>。定义泛型接口与定义泛型类所用的技术相同,例如: interface ...
  • C# 泛型,泛型约束,泛型接口

    千次阅读 2013-04-16 17:18:11
    C#泛型  泛型(使用System.Collections.Generic命名空间)是C#语言2.0和通用语言运行时(CLR)的一个新特性。泛型为.NET框架引入了类型参数(type parameters:不必确定一个或多个具体参数,属于同一类即可。这就...
  • 泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。
  • 泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。...更重要的是,C#泛型比C++的模板使用更加安全,并且通过避免装箱和拆箱操作来达到性能提
  • 使用泛型定义一个父类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Practice { public class Power<T1,T2,T3> { ...
  • C#泛型实例详解

    2020-12-26 03:14:00
    本文以实例形式讲述了C#泛型的用法,有助于读者深入理解C#泛型的原理,具体分析如下: 首先需要明白什么时候使用泛型: 当针对不同的数据类型,采用相似的逻辑算法,为了避免重复,可以考虑使用泛型。 一、针对类的...
  • C#泛型的协变与逆变

    2022-07-10 17:52:36
    当我们使用泛型编程时,可能会遇到如下问题,即将一个较具体的类型赋值给一个较泛化的类型是可行的,但在泛型中却无法编译通过。 用不同类型参数声明同一个泛型...我们可以假设C#允许泛型协变,看一下会发生什么: 可以
  • 时已经接触了泛型接口,有几个要注意的内容: 1. 泛型接口为不变量, 例如 IWrapper<T>, 不能将IWrapper<object>对象赋值给IWrapper<string>,即使string派生与object类型。 2. 协变接口, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,820
精华内容 12,728
关键字:

c#泛型接口