《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)
1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还记得在继承中,子类可以隐式转化成父类,这是因为他们之间的继承关系。若是两个没有关系的类之间要进行转化的话就需要自定义类型转化。自定义的类型转化必须为静态类型,需要explicit关键字或者implicit关键字以及operator关键字格式大体上是:访问修饰符 static implicit/explicit operator 返回值类型(参数类型 oparam)。自定义类型转化的重点在于只要代码没错,就可以按你自己的想法对任何的不相干的类型进行转化。例:
namespace ExplicitAndImplicit
{
class Program
{
static void Main(string[] args)
{
B b = new B(10);
A a = (A)b;
Console.WriteLine(a.ToString());
Console.ReadLine();
}
}
public struct A
{
public int W { get; set; }
public int H { get; set; }
public A(int w, int h) : this()
{
W = w;
H = h;
}
public override string ToString()
{
return string.Format("W={0},H={1}",W,H);
}
public static explicit operator A(B b)
{
A a = new A();
a.W = b.L * 2;
a.H = b.L;
return a;
}
}
public struct B
{
public int L { get; set; }
public B(int l) : this()
{
L = l;
}
}
}
结果:
可见转化是成功的。在转化时,返回值或者参数类型中必须要有一个是该封闭类。在例子中显示链接到了默认构造函数,书上说原因是如果结构使用了自动属性,所有的自定义构造函数必须显示调用默认构造函数,来初始化私有的后台字段,但是我在删除链接之后,结果依然,因而这个结论记住就好,若是遇到错误时刻添加试试,有人知道这是什么原因的话可以留言一起讨论。
2.扩展方法是在已经定义一个类,在不打算改变类的内部结构时或者无法派生时,在外部添加所需要的新需求的一种方法,在定义扩展方法的时候必须要定义在静态类中,因此,每个扩展方法也必须定义为静态类,其次就是在扩展方法时要将第一个参数用this进行修饰,要用this限定的参数表示被扩展的项,例:
static class Extensions
{
public static int ReverseDigits(this int i)//this修饰参数,表示被扩展的项
{
char[] digits=i.ToString().ToCharArray();//把int翻译为string然后获取所有字段
Array.Reverse(digits);//反转数组中的项
string newDigits=new String(digits);//返回string
return int.Parse(newDigits);
}
}
static void Main(string[] args)
{
int digit=1234;
console.writeline(digit.ReverseDigits());
}
以上的例子我是写在同一个命名空间内,若是不在一个一个命名空间,则在调用扩展方法之前,需先引入扩展方法所在的命名空间。同时,我们还可以定义一个扩展方法,使只有正确的实现接口的类或者结构才可以使用。比如我们定义一个只有实现了IEnumerable<T>,才可以调用该扩展方法,例:
static class Extensions
{
public static void PrintItem(this system.collections.IEnumerable item)
{
foreach(var i in item)
{
console.writeLine(i);
}
console.ReadLine();
}
}
static void Main(string[] args)
{
string[] s={"1","2","3","4"};
s.PrintItem();
}
3.匿名类型:有时候我们需要定义一个类来封装一些数据,都不需要任何的方法以及功能,并且这个类只有少量的方法会使用它,对于这样的类似于临时数据,我们如果特意封装一个类无疑是一种浪费,所以我们可以使用var关键字来定义一个匿名类型,定义方法和对象初始化器非常相识,只是在new与{}间的类名没有了,编译器会在编译时自动生成新的类的定义,初始化语法将会告诉编译器胃新建的类型创建私有的后台字段和只读属性。例如我们在项目中,我们时常会需要从数据库取出取数据,但是又不需要用到表格中的所有的字段,这个时候就是会用到匿名类型,这个方法在目前为止,我大部分和linq用在一起,很好用。匿名方法无法控制类型的名称,由编译器自己创建,自动基础object,它的字段以及属性都是只读的,不支持事件,自定义方法,自定义操作符和自定义重写,匿名类型是隐式封闭的,不可继承的,在创建实例是只能使用默认构造函数等都是它的限制。至于它的其余特性,可观看http://www.cnblogs.com/skykang/archive/2011/03/03/1970194.html的内容,这位作者写的很详细了。在我个人看来,使用匿名类型封装数据最好是在需要封装多种不同类型的数据时,以目前的经验来说,mvc中的model就是一个专门封装数据的类。
4.指针类型:在什么场合需要用到指针类型呢?一是在要绕过CLR管理直接操作指针已优化应用程序的特定部分,二是要调用基于C的dll或调用需要指针作为参数的COM服务器。但是即使在这种情况下也可以使用system.InPtr类型和System.Runtime.InteropServices.Marshal类型的成员,而不使用指针类型。要使用指针就需要通过项目支持不安全代码,我们不仅需在开发环境中设置允许不安全代码以外,还需要使用unsafe关键字特别声明一个代码区域,可以使用*操作符构建数据类型的指针,使用&操作符获取被指向的内存地址,使用->访问公共成员,但是也可以使用(*)来解除指针的引用,使其也可以使用点操作符访问字段,例:
struct Point
{
public int x;
public int y;
public override string Tostring()
{
return string.Format("({0},{1})",x,y);
}
}
unsafe static void UsePointerToPoint()
{
//通过指针访问成员
Point point;
Point* p=&point;
p->x=100;
p->y=200;
console.writeline(p->Tostring());
//通过指针间接寻址访问成员
Point point2;
Point* p2=&point2;
(*p2).x=100;
(*p2).y=200;
console.writeline(p->Tostring());
}
对指针这个C#特性,因为涉及太多,忍痛略过,将来有机会在详谈.
《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)的更多相关文章
- C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数
一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...
- [Swift通天遁地]五、高级扩展-(3)日期和时间类型的扩展方法
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- dynamic动态类型的扩展方法
对于一个动态类型来说,你可以认为它包含任意成员,它们都能通过编译.但到了运行时,到底是否拥有这些成员,就真相大白了.如 dynamic test = ; Console.Write(test.Name ...
- 编写高质量代码改善C#程序的157个建议——建议101:使用扩展方法,向现有类型“添加”方法
建议101:使用扩展方法,向现有类型“添加”方法 考虑如何让一个sealed类型具备新的行为.以往我们会创建一个包装器类,然后为其添加方法,而这看上去一点儿也不优雅.我们也许会考虑修改设计,直接修改s ...
- typescript 添加基础类型的扩展方法
以时间转换为案例: //声明接口,也是在声明date这个基础类型要定义一个format的扩展方法,不写接口声明会报错 interface Date { Format(fmt:string):strin ...
- 040_字符串连接符 041_条件运算符目 042_运算符优先级_逻辑与或优先问题 043_自动类型转化 044_强制类型转换 045_基本类型常见错误_溢出_L问题
040_字符串连接符 package test_package; /** * 字符串运算符 * @author * */public class TestOperator05 { public sta ...
- 21扩展IEnumerable<T>泛型接口自定义LINQ的扩展方法
LINQ方法实际上是对IEnumerable<TSource>的扩展,如图: 本篇自定义一个MyWhere方法,达到与Where相同的效果. 使用LINQ自带的Where方法 ...
- Path类型的扩展方法 z
写了一个基于System.IO.Path类型方法的扩展类型,用于快速对文件系统路径进行操作.如下图: 其中有许多方法就是直接调用Path类型的静态方法.比如AppendPath方法内部会直接调用Pat ...
- Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)
Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...
随机推荐
- 【日常小记】linux中强大且常用命令:find、grep【转】
转自:http://www.cnblogs.com/skynet/archive/2010/12/25/1916873.html 在linux下面工作,有些命令能够大大提高效率.本文就向大家介绍fin ...
- JDK在Linux系统上安装教程
一.下载jdk相应版本(我用的是jdk-8u111-linux-x64) 下载地址去官网:http://www.oracle.com/technetwork/cn/java/javase/down ...
- 【python】如何在某.py文件中调用其他.py内的函数
假设名为A.py的文件需要调用B.py文件内的C(x,y)函数 假如在同一目录下,则只需 import B if __name__ == "__main__": B.C(x,y) ...
- 2016湖大校赛 L题 The Sequence likes Ladder
题意:S1=a,Sn=a*(Sn-1)^k%m,且有(a,m)=1,给出i,求Si. 思路:首先我们可以写出Sn的通项a^(1+k+k^2+...k^n-1);其次注意到m的范围是10000以内,所以 ...
- 前端之CSS(二)
一.盒子模型 说到盒子模型,我们不得不提一下,W3C标准和IE浏览器是有区别的,我昨天就在写抽屉作业的时候踩过坑,建议用谷歌浏览器,并推荐一篇博文:http://www.osmn00.com/tran ...
- AChecker + Selenium2对需要登录的页面进行自动化可访问性测试
前言:这段时间还算比较空闲,我准备把过去做过的有些形形色色,甚至有些奇怪的研究总结一下,也许刚好有人用的着也不一定,不枉为之抓耳挠腮的时光和浪费的电力. 名词解释: 网站可访问性测试:国内基本没有 ...
- TFS二次开发系列:八、TFS二次开发的数据统计以PBI、Bug、Sprint等为例(二)
上一篇文章我们编写了此例的DTO层,本文将数据访问层封装为逻辑层,提供给界面使用. 1.获取TFS Dto实例,并且可以获取项目集合,以及单独获取某个项目实体 public static TFSSer ...
- 远程调试 ASP.NET MVC 项目
Visual Studio 支持从一台计算机到另一台设备的远程调试.进行远程调试时,主机可以是任何支持 Visual Studio 的平台.远程设备可以是 x86.x64 或 ARM 平台. 本文将指 ...
- 点燃圣火! Ember.js 的初学者指南
现在,到处都可以看到复杂的 JavaScript 应用程序. 由于这些应用程序变得越来越复杂,一长串的 jQuery 回调语句,或者通过应用程序在各个点执行不同的函数调用,这些都变得无法再让人接受. ...
- ie6、7 下input的边框问题 ?
input的border设置为none,ie8及以上border都兼容,ie6和7的border还继续存在,将border设为0时所有浏览器上都不存在了,但是border为0时还是会继续的渲染. 将i ...