十一、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)’. ...
随机推荐
- 【HDOJ】1728 逃离迷宫
题目大坑,注意行列顺序式反的,另外注意起点和终点相同. #include <iostream> #include <cstdio> #include <cstring&g ...
- 成为Web开发人员的7个简单步骤
你想成为一名 Web 开发人员,但现在你面前有这样一个问题,那就是你没有在高科技行业工作的经验.你上了一些课程,也花了时间在个人编码项目上,但是你的简历上关于“经验”的部分仍然不为企业承认.过渡到一个 ...
- HDOJ1253 胜利大逃亡 BFS
胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...
- XCode4 下制作Framework的方法
http://www.cocoachina.com/bbs/read.php?tid-75680-page-1.html
- Torque2D MIT 学习笔记(27) ---- ImageFont的使用以及字体ImageAsset的工具生成
前言 ImageFont继承于SceneObject,是一个场景对象,支持例如旋转,缩放,移动加速度以及物理碰撞等一切Torque中场景对象的一切功能. ImageFont只支持ASCII编码表中的3 ...
- Delphi:窗体自适应屏幕分辨率的改进
在窗体依据屏幕分辨率自适应调整尺度方面,昨天的工作可以说是一个突破点.昨天的工作找到了长期以来我的原有方案的问题所在,这是非常关键的.但是昨天晚上的解决方案并不完美,今天的这个才是比较完美的解决版. ...
- 数据结构学习笔记——stack实现(数组篇)
一 栈:是一种表,限制插入和删除只能在一个位置,也即是表的末端(也是栈的顶)进行. 基本操作:push 和 pop. 二 栈的数组实现: 运用数组来存储元素,和栈操作先关的是theArray(一个数组 ...
- 部署MongoDB扩展并测试使用php简单连接操作之
1,下载MongoDB数据库扩展介质 wget http://pecl.php.net/get/mongo-1.5.1.tgz 2,tar zxvf mongo-1.5.1.tgz &&am ...
- UVA 465 (13.08.02)
Overflow Write a program that reads an expression consisting of twonon-negative integer and an ope ...
- hud 1241 dfs连同块
Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...