十一、C# 泛型
public class Stack<T>
{
private T[] _Items; public void Push(T data)
{ } public void Pop()
{ }
}
2、编译时类型检查减少了在运行时发生InvalidCastException异常的几率。
3、为泛型类成员使用值类型,不再造成object的类型转换,它们不再需要装箱操作。
4、C#中的泛型缓解了代码膨胀的情况。
5、性能得到了提高。一个原因是不再需要从object的强制转换,从而避免了类型检查。
另一个是不再需要为值类型执行装箱。
6、泛型减少了内存消耗。由于避免了装箱,因此减少了堆上的内存的消耗。
7、代码的可读性更好。
8、支持IntelliSense的代码编辑器现在能直接处理来自泛型类的返回参数。没有必要为了使IntelliSense工作起来,而对返回
数据执行转型。
interface IPair<T>
{
T First { get; set; }
T Second { get; set; }
}
public struct Pair<T> : IPair<T>
{
private T _First;
public T First
{
get
{
return _First;
}
set
{
_First = value;
}
}
private T _Second;
public T Second
{
get
{
return _Second;
}
set
{
_Second = value;
}
} }
public interface IContainer<T>
{
ICollection<T> Items
{ set; get; }
}
public class Address
{
}
public class Phone
{
}
public class Email
{
} public class Person : IContainer<Address>, IContainer<Phone>, IContainer<Email>
{
ICollection<Address> IContainer<Address>.Items
{ set; get; } ICollection<Phone> IContainer<Phone>.Items
{ set; get; } ICollection<Email> IContainer<Email>.Items
{ set; get; }
}
interface IPair<T>
{
T First { get; set; }
T Second { get; set; }
}
public struct Pair<T> : IPair<T>
{
public Pair(T first, T second)
{
_First = first;
_Second = second;
}
private T _First;
public T First
{
get
{
return _First;
}
set
{
_First = value;
}
}
private T _Second;
public T Second
{
get
{
return _Second;
}
set
{
_Second = value;
}
} }
public Pair(T first)
{
_First = first;
_Second = default(T);
}
interface IPair<TFirst,TSecond>
{
TFirst First { get; set; }
TSecond Second { get; set; }
}
public struct Pair<TPFirst, TPSecond> : IPair<TPFirst, TPSecond>
{
public Pair(TPFirst first,TPSecond second)
{
_First = first;
_Second = second;
}
private TPFirst _First;
public TPFirst First
{
get
{
return _First;
}
set
{
_First = value;
}
}
private TPSecond _Second;
public TPSecond Second
{
get
{
return _Second;
}
set
{
_Second = value;
}
} }
class Program
{
static void Main(string[] args)
{ Pair<int, string> historicalEvent = new Pair<int, string>(, "Shackletion leaves for South Pole on ship Endurance");
Console.WriteLine("{0}:{1}",historicalEvent.First,historicalEvent.Second); }
}
public static class Tuple
{
// 摘要:
// 创建新的 1 元组,即单一实例。
//
// 参数:
// item1:
// 元组仅有的分量的值。
//
// 类型参数:
// T1:
// 元组的唯一一个分量的类型。
//
// 返回结果:
// 值为 (item1) 的元组。
public static Tuple<T1> Create<T1>(T1 item1);
//
// 摘要:
// 创建新的 2 元组,即二元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// 返回结果:
// 值为 (item1, item2) 的 2 元组。
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2);
//
// 摘要:
// 创建新的 3 元组,即三元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3) 的 3 元组。
public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3);
//
// 摘要:
// 创建新的 4 元组,即四元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// item4:
// 此元组的第四个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// T4:
// 此元组的第四个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3, item4) 的 4 元组。
public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4);
//
// 摘要:
// 创建新的 5 元组,即五元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// item4:
// 此元组的第四个分量的值。
//
// item5:
// 此元组的第五个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// T4:
// 此元组的第四个分量的类型。
//
// T5:
// 此元组的第五个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3, item4, item5) 的 5 元组。
public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5);
//
// 摘要:
// 创建新的 6 元组,即六元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// item4:
// 此元组的第四个分量的值。
//
// item5:
// 此元组的第五个分量的值。
//
// item6:
// 此元组的第六个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// T4:
// 此元组的第四个分量的类型。
//
// T5:
// 此元组的第五个分量的类型。
//
// T6:
// 此元组的第六个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3, item4, item5, item6) 的 6 元组。
public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6);
//
// 摘要:
// 创建新的 7 元组,即七元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// item4:
// 此元组的第四个分量的值。
//
// item5:
// 此元组的第五个分量的值。
//
// item6:
// 此元组的第六个分量的值。
//
// item7:
// 元组的第七个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// T4:
// 此元组的第四个分量的类型。
//
// T5:
// 此元组的第五个分量的类型。
//
// T6:
// 此元组的第六个分量的类型。
//
// T7:
// 元组的第七个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3, item4, item5, item6, item7) 的 7 元组。
public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7);
//
// 摘要:
// 创建新的 8 元组,即八元组。
//
// 参数:
// item1:
// 此元组的第一个分量的值。
//
// item2:
// 此元组的第二个分量的值。
//
// item3:
// 此元组的第三个分量的值。
//
// item4:
// 此元组的第四个分量的值。
//
// item5:
// 此元组的第五个分量的值。
//
// item6:
// 此元组的第六个分量的值。
//
// item7:
// 元组的第七个分量的值。
//
// item8:
// 元组的第八个分量的值。
//
// 类型参数:
// T1:
// 此元组的第一个分量的类型。
//
// T2:
// 元组的第二个分量的类型。
//
// T3:
// 元组的第三个分量的类型。
//
// T4:
// 此元组的第四个分量的类型。
//
// T5:
// 此元组的第五个分量的类型。
//
// T6:
// 此元组的第六个分量的类型。
//
// T7:
// 元组的第七个分量的类型。
//
// T8:
// 元组的第八个分量的类型。
//
// 返回结果:
// 值为 (item1, item2, item3, item4, item5, item6, item7, item8) 的 8 元祖(八元组)。
public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8);
}
class Container<T, U>
{
class Nested<U>
{
void Method(T param0, U param1)
{ }
}
}
public class BinaryTree<T> where T : System.IComparable<T>
{ }
public class BinaryTree<T> where T : Phone
{ }
public class BinaryTree<T> where T : struct
{ }
public class BinaryTree<T> where T : class
{ }
public class BinaryTree<T, U> : Container<T, U>
where T : IComparable<T>, IFormattable
where U : Phone
{ }
public class BinaryTree<T, U> : Container<T, U>
where T : IComparable<T>, IFormattable
where U : Phone,new ()
{ }
public class EntityBase<T> where T:IComparable<T>
{ }
public class Entity<T> : EntityBase<T> where T : IComparable<T>
{ }
public class EntityBase<T> where T:IComparable<T>
{
public virtual void Method<T>(T t)
where T : IComparable<T>
{ }
}
public class Entity<T> : EntityBase<T> where T : IComparable<T>
{
public override void Method<T>(T t)
{ }
}
public static class MathEx
{
public static T Max<T>(T first, params T[] values)
where T : IComparable<T>
{
T maximun = first;
foreach (T item in values)
{
if (item.CompareTo(maximun) > )
{
maximun = item;
}
}
return maximun;
}
}
Console.WriteLine(MathEx.Max<int>(, ));
Console.WriteLine(MathEx.Max<string>("R.O.U.S.","Fireswamp")); Console.WriteLine(MathEx.Max(, ));
Console.WriteLine(MathEx.Max("R.O.U.S.","Fireswamp"));
public virtual void Method<T>(T t)
where T : IComparable<T>
{ }
class Program
{
static void Main(string[] args)
{
//只有接口和委托可以使用in out修饰
Pair<Contact> contacts = new Pair<Contact>(new Contact("Princess Buttercupt", DateTime.Now),
new Contact("Inigo Montoya", DateTime.Now));
//IPair<PdaItem> pair = contacts;//因为没有使用out ,不允许协变
IReadOnlyPair<PdaItem> readPair = contacts;
//异质:泛型指定的参数数据类型与实际的数据类型不同且非继承关系()
//异质的产生:
//因为如果允许从子类往上转型成了基类,理论上可以改变 pair.ReadOnlyFirst = new Address();
//因为Address是PdaItem的子类 会造成数据的异质
//本来只允许包含的是Contact类型(T被指定为Contact),现在却包含了Address 这个没有直接关系的类型
//所以才需要使用通过out修饰限制泛型类型声明,让它只向接口的外部公开数据 PdaItem pdaItem1 = readPair.ReadOnlyFirst;//只可读取,不可设置
PdaItem pdaItem2 = readPair.ReadOnlySecond;
Console.WriteLine(pdaItem1.Name + " " + pdaItem1.LastUpdated);
Console.WriteLine(pdaItem2.Name + " " + pdaItem2.LastUpdated); }
}
public class PdaItem
{
public PdaItem()
{
}
public PdaItem(string pName, DateTime pLastUpdated)
{
Name = pName;
LastUpdated = pLastUpdated;
}
public virtual string Name { set; get; } public DateTime LastUpdated { set; get; }
} public class Contact : PdaItem
{
public override string Name
{
get
{
return FirtstName;
}
set
{
FirtstName = value + " from Contact";
}
}
private string FirtstName;
public Contact()
{
}
public Contact(string pName, DateTime pLastUpdated)
: base(pName, pLastUpdated)
{ } } public class Address : PdaItem
{
public override string Name
{
get
{
return DetailAddress;
}
set
{
DetailAddress = value + " from Address";
}
}
//此处会造成与Contact数据不一,从而造成泛型的数据异质
private string DetailAddress;
public string address1;
public string address2;
public string address3;
public Address()
{
}
public Address(string pName, DateTime pLastUpdated)
: base(pName, pLastUpdated)
{ } } interface IReadOnlyPair<out T>
{
T ReadOnlyFirst { get; }
T ReadOnlySecond { get; }
}
interface IPair<T>
{
T First { get; set; }
T Second { get; set; }
}
public struct Pair<T> : IPair<T>, IReadOnlyPair<T>
{ public Pair(T first, T second)
{
TPFirst = TPFirstReadOnly = first;
TPSecond = TPSecondReadOnly = second;
}
private T TPFirst;
private T TPSecond;
private T TPFirstReadOnly;
private T TPSecondReadOnly; T IPair<T>.First
{
get
{
return TPFirst;
}
set
{
TPFirst = value;
}
}
T IPair<T>.Second
{
get
{
return TPSecond; }
set
{
TPSecond = value;
}
}
T IReadOnlyPair<T>.ReadOnlyFirst
{
get
{
return TPFirstReadOnly;
}
}
T IReadOnlyPair<T>.ReadOnlySecond
{
get
{
return TPSecondReadOnly;
} }
}
class Program
{
static void Main(string[] args)
{
//只有接口和委托可以使用in out修饰
Pair<Contact> contacts = new Pair<Contact>(new Contact("Princess Buttercupt", DateTime.Now),
new Contact("Inigo Montoya", DateTime.Now));
//IPair<PdaItem> pair = contacts;//因为没有使用out ,不允许协变
IReadOnlyPair<PdaItem> readPair = contacts;
//异质:泛型指定的参数数据类型与实际的数据类型不同且非继承关系()
//异质的产生:
//因为如果允许从子类往上转型成了基类,理论上可以改变 pair.ReadOnlyFirst = new Address();
//因为Address是PdaItem的子类 会造成数据的异质
//本来只允许包含的是Contact类型(T被指定为Contact),现在却包含了Address 这个没有直接关系的类型
//所以才需要使用通过out修饰限制泛型类型声明,让它只向接口的外部公开数据 PdaItem pdaItem1 = readPair.ReadOnlyFirst;//只可读取,不可设置
PdaItem pdaItem2 = readPair.ReadOnlySecond;
Console.WriteLine(pdaItem1.Name + " " + pdaItem1.LastUpdated);
Console.WriteLine(pdaItem2.Name + " " + pdaItem2.LastUpdated); //从基类转换成子类的泛型
Pair<PdaItem> pdaitem = new Pair<PdaItem>(new Contact("Princess Buttercupt", DateTime.Now),
new Address());
IWriteOnlyPair<Contact> writePair = pdaitem;
//此处是重点,通过这个接口 1、只能进行赋值且只能是Contact类型或者它的子类,而不能是Address类型(非相关类型) 2、不能进行访问
//这样就避免了,当pdaitem有多个不同类型的项时,使用一个泛型(T为子类类型)接口访问数据时,产生错误。因为类型不同,内部的成员变量和方法也有可能不同。 writePair.WriteOnlyFirst = new Contact();
writePair.WriteOnlySecond = new Contact(); }
}
public class PdaItem
{
public PdaItem()
{
}
public PdaItem(string pName, DateTime pLastUpdated)
{
Name = pName;
LastUpdated = pLastUpdated;
}
public virtual string Name { set; get; } public DateTime LastUpdated { set; get; }
} public class Contact : PdaItem
{
public override string Name
{
get
{
return FirtstName;
}
set
{
FirtstName = value + " from Contact";
}
}
private string FirtstName;
public Contact()
{
}
public Contact(string pName, DateTime pLastUpdated)
: base(pName, pLastUpdated)
{ } } public class Address : PdaItem
{
public override string Name
{
get
{
return DetailAddress;
}
set
{
DetailAddress = value + " from Address";
}
}
//此处会造成与Contact数据不一,从而造成泛型的数据异质
private string DetailAddress;
public string address1;
public string address2;
public string address3;
public Address()
{
}
public Address(string pName, DateTime pLastUpdated)
: base(pName, pLastUpdated)
{ } } interface IReadOnlyPair<out T>
{
T ReadOnlyFirst { get; }
T ReadOnlySecond { get; }
}
interface IWriteOnlyPair<in T>
{
T WriteOnlyFirst { set; }
T WriteOnlySecond { set; }
}
interface IPair<T>
{
T First { get; set; }
T Second { get; set; }
}
public struct Pair<T> : IPair<T>, IReadOnlyPair<T>, IWriteOnlyPair<T>
{ public Pair(T first, T second)
{
TPFirst = TPFirstWriteOnly = TPFirstReadOnly = first;
TPSecond = TPSecondWriteOnly = TPSecondReadOnly = second;
}
private T TPFirst;
private T TPSecond;
private T TPFirstReadOnly;
private T TPSecondReadOnly; private T TPFirstWriteOnly;
private T TPSecondWriteOnly; //以下都是显式实现接口,使用时,需要进行显式转换才可以使用
T IPair<T>.First
{
get
{
return TPFirst;
}
set
{
TPFirst = value;
}
}
T IPair<T>.Second
{
get
{
return TPSecond; }
set
{
TPSecond = value;
}
}
T IReadOnlyPair<T>.ReadOnlyFirst
{
get
{
return TPFirstReadOnly;
}
}
T IReadOnlyPair<T>.ReadOnlySecond
{
get
{
return TPSecondReadOnly;
} }
T IWriteOnlyPair<T>.WriteOnlyFirst
{
set
{
TPFirstWriteOnly = value;
}
}
T IWriteOnlyPair<T>.WriteOnlySecond
{
set
{
TPSecondWriteOnly = value;
} }
}
interface IConvertible<in TSource, out TTarget>
{
TTarget Convert(TSource s);
}
十一、C# 泛型的更多相关文章
- JAVA之旅(二十一)——泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符
JAVA之旅(二十一)--泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符 不知不觉JAVA之旅已经写到21篇了,不得不感叹当初自己坚持要重学一遍JAVA的信念,中途也算 ...
- C#编程(三十一)----------泛型总结
C#泛型总结 C#中的所谓的泛型程序设计和C++中相应的模版类似. 泛型方法 C#中的泛型方法是指使用了类型参数的方法成员,案例: static void Main(string[] args) { ...
- 第十一章 泛型算法 C++ PRIMER
vector<int>::const_iterator result = find(vector.begin(). vector.end(),search_value); 如果查找失败,分 ...
- Autofac 组件、服务、自动装配 《第二篇》
一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...
- Autofac 组件、服务、自动装配(2)
一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...
- <C++Primer>第四版 阅读笔记 第二部分 “容器和算法”
泛型算法中,所谓"泛型(generic)"指的是两个方面:这些算法可作用于各种不同的容器类型,而这些容器又可以容纳多种不同类型的元素. 第九章 顺序容器 顺序容器的元素排列次序与元 ...
- JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!
JAVA之旅(三十五)--完结篇,终于把JAVA写完了,真感概呐! 这篇博文只是用来水经验的,写这个系列是因为我自己的java本身也不是特别好,所以重温了一下,但是手比较痒于是就写出了这三十多篇博客了 ...
- Java开发快速上手
Java开发快速上手 前言 1.我的大学 2.对初学者的建议 3.大牛的三大特点 4.与他人的差距 第一章 了解Java开发语言 前言 基础常识 1.1 什么是Java 1.1.1 跨平台性 1.2 ...
- Autofac框架详解
一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...
- 【.Net】net 反射15分钟速成
概述 什么是反射 Reflection,中文翻译为反射. 这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’.‘模块(Module)’. ...
随机推荐
- 【转】MongoDB资料汇总专题
1.MongoDB是什么 MongoDB介绍PPT分享 MongoDB GridFS介绍PPT两则 初识 MongoDB GridFS MongoDB GridFS 介绍 一个NoSQL与MongoD ...
- HDOJ1020 Encoding
Problem Description Given a string containing only 'A' - 'Z', we could encode it using the following ...
- java 内存泄露 学习
1.什么事内存泄露 内存泄露就是对象不用了,但是无法回收该对象占用的内存. 2.java不是有垃圾回收机制,咋还会发生内存泄露呢? java的垃圾回收机制就是把无用的对象(GC roots可达与否)用 ...
- Python参数中的*和**
def funct3(x, y=1, z=1, *tup): print((x, y, z) + tup) def funct4(x, y=1, z=1, **dictionary): print(x ...
- hdu 4403 枚举
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #inclu ...
- Tomcat绑定多个IP地址 多域名绑定
http://blog.csdn.net/stevenyanzhi/article/details/6029776 Tomcat绑定多个IP地址 如果一台服务机上有多个IP地址又有多个工程如何一个IP ...
- 自动布局AutoLayout
1:理解概念 Auto Layout 中文翻译过来意思是 自动布局 ,通过内定的 Constraint (约束)和各项条件来计算出合理的布局.而这个合理的布局,符合我们的的预期和意图. 将我们想象中的 ...
- Winform Windows Media Player 简易播放器 分类: WinForm 2014-07-31 20:12 589人阅读 评论(0) 收藏
新手上路,高手勿进! 窗体设计: 实现效果: 实现代码: using System; using System.Collections.Generic; using System.ComponentM ...
- 今天就注册上海ORACLE2用户组014在峰会酒吧!
COLLABORATE 14 – SHOUG Forum 上海ORACLE用户组2014年高峰论坛报名本次活动由ORACLE ACS高级服务部门与 SHOUG 上海ORACLE用户组合办. 大会议程包 ...
- 学习NodeJS第一天:node.js引言
Node.JS 是资深 C 程序猿 Ryan Dahl(http://four.livejournal.com/)的作品,根据 Google 著名的开源 JavaScript 引擎 V8 来进行二次开 ...