《精通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结合的例子,顺便对各 ...
随机推荐
- 使用httpclient发送http请求
先来个httpclient的maven依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> &l ...
- 处理handler中的内存泄漏
package de.bvb.test; import android.app.Activity; import android.os.Bundle; import android.os.Handle ...
- apache commons math 示例代码
apache commons Math是一组偏向科学计算为主的函数,主要是针对线性代数,数学分析,概率和统计等方面. 我虽然是数学专业毕业,当年也是抱着<数学分析>啃,但是好久不用,这些概 ...
- maven 打war包tomcat服务器乱码问题
今天用maven3的命令打war包,命令是mvn clean package -Dmaven.test.skip=true,打包后放在tomcat跑起来后发现tomcat的日志出现乱码. 后来在pom ...
- Linux手绑IP
修改配置文件vim /etc/sysconfig/network-scripts/ifcfg-eth0 注释dhcp#BOOTPROTO="dhcp" 注释ipv6#IPV6INI ...
- zigbee学习之路(十一):看门狗
一.前言 今天,我们要通过实验学习和认识一下看门狗的使用,看门狗是为了防止防止程序跑飞的,通过不断的喂狗,使看门狗能持续监管程序的运行状态,当程序跑飞时,能及时把程序拽回来. 二.原理与分析 在CPU ...
- 关于工程结合git的配置
我们通常把代码放到git sever中,(scm manager)中,上传,下载代码, 可是通常工程的代码改动会有图标提示,改动过的,或者新增的,那么需要在eclipse的工程中做一下简单配置 1,工 ...
- 微信小程序-位置坐标
wx.getLocation(OBJECT) 获取当前的地理位置.速度. OBJECT参数说明: success返回参数说明: 示例代码: wx.getLocation({ type: 'wgs84' ...
- js : json和 cookie 的简单操作
使用 cookie,可以记录用户的最近的浏览历史 <!DOCTYPE HTML> <html lang="zh-cn"> <head> < ...
- 谈谈Memcached与Redis
1. Memcached简介 Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器.其本质上就是一个 ...