1.对象初始化器

    class Curry
{
public string MainIngredient{get;set;}
public string Style { get; set; }
public int Speciness { get; set; }
}

假如有如上一个类,当我们创建这个类的对象之后需要分别给每个属性赋值

            Curry curry=new Curry();
curry.MainIngredient = "painr tikka";
curry.Style = "jal";
curry.Speciness = ;

这样显得非常麻烦,使用对象初始化器可以简化对象创建和初始化的过程。这段代码会调用默认的构造函数创建对象,对象创建之后在给对象属性赋值。也可以在new之后指定使用的构造函数

Curry test = new Curry { MainIngredient = "painr tikka", Style = "jal", Speciness =  };
    class Curry
{
public string MainIngredient{get;set;}
public string Style { get; set; }
public int Speciness { get; set; } public Curry()
{ } public Curry(int speciness)
{
Speciness = speciness;
}
} Curry test = new Curry() { MainIngredient = "painr tikka", Style = "jal"};

 2.集合初始化器

List<int> primes = new List<int>() { , , , ,  };

集合初始化器会默认调用集合的Add方法来初始化集合,如果集合没有改方法将报错。

3.var关键字

C#3.0引入新的关键字var,允许使用var关键字定义需要编译器辅助确认类型的变量。它并不是创建没有类型或者类型可以变的变量。使用var需要注意:

1)使用var定义的变量声明和初始化必须一起,不能分开,比如var a ; a=0是错误的,正确的是var a =0;

2) var只能定义局部变量,不能定义全局变量;

3)变量初始化之后变量的类型就固定了,不能再用别的类型赋值。

可以使用var声明数组,比如var array =new []{4,5,6},但是数组初始化器的数据必须满足以下条件之一:

1)相同的类型;

2)相同的引用类型或null;

3)所有元素的类型都可以隐式的转换为一种类型。

 4.匿名类型

为了显示数据,我们经常需要建一些简单的类,这些类只有简单的的几个属性,而且如果数据改变了又要更新这个类,最不爽的是这个类仅仅在某个地方用了一下下。比如如下一个类

    class Curry
{
public string MainIngredient { get; set; }
public string Style { get; set; }
public int Spicinesss { get; set; }
}

不想建数据类型,匿名类型可以帮我们动态建立一个类型,它会根据我们初始化的数据建立类型。比如如下代码建立了一个匿名类型

                var curry = new {
MainIngredient = "Lamb",
Style="Dhansak",
Spicinesss=
};

匿名类型的特征是new后面没有数据类型,这也是编译器确定匿名类型的方式。因为匿名类型没有类型名称,所以只能在当前代码块中使用创建的匿名类型

匿名类型与Equals、GetHashCode、==

    class Curry
{
public string MainIngredient { get; set; }
public string Style { get; set; }
public int Spicinesss { get; set; }
} class Program
{ static void Main(string[] args)
{
try
{
var curries = new[]{
new {
MainIngredient = "Lamb",
Style="Dhansak",
Spicinesss=
},
new {
MainIngredient = "Lamb",
Style="Dhansak",
Spicinesss=
},
new {
MainIngredient = "Chicken",
Style="Dhansak",
Spicinesss=
}
}; Console.WriteLine(curries[].Equals(curries[]));
Console.WriteLine(curries[].Equals(curries[]));
Console.WriteLine(curries[].GetHashCode());
Console.WriteLine(curries[].GetHashCode());
Console.WriteLine(curries[].GetHashCode());
Console.WriteLine(curries[] == curries[]);
Console.WriteLine(curries[] == curries[]); }
catch (RuntimeBinderException ex)
{
Console.WriteLine(ex.Message);
} Console.ReadLine();
}
}

通过以上代码发现匿名类型使用Equals方法时比较的是它们的值是否相等,而不是比较引用;

GetHashCode因为curries[0]、curries[1]两个对象的值相同,所以它们的状态相同,返回的值也就相同。

==比较的是两个对象的引用curries[0]、curries[1]属于两个不同对象,引用不同。

5.动态查找

C#4.0引入了动态变量,动态变量顾名思义就算类型可变的变量。引入动态变量的目的在于使用C#处理另一种语言创建的对象,包括与旧及时今日交互,比如Component Object Model(Com),以及处理JavaScript、ruby、python等动态语言。

比如代码从JavaScript中获取一个Add()方法,该方法把两个参数加在一起。如果没有动态查找功能就需要这样访问Add()方法

ScriptObject jsObj = SomeMethodGetTheObject();
int sum=Convert.ToInt32(jsObj.Invoke("Add", , ));

如果使用动态查找就可以直接调用方法

ScriptObject jsObj = SomeMethodGetTheObject();
int sum=Convert.ToInt32(jsObj.Add(, ));

动态查找方法可以根据变量的具体类型,动态的查找该类型是否有Add方法,如果没有该方法会引发一个RuntimeBinderException异常。

如下是一个使用动态查找的例子

namespace ConsoleApplication1
{
class Program
{ static void Main(string[] args)
{
try
{
dynamic firstResult = GetValue();
dynamic secondResult = GetValue(); Console.WriteLine("firstResult is :" + firstResult.ToString());
Console.WriteLine("secondResult is :" + secondResult.ToString());
Console.WriteLine("firstResult call :" + firstResult.Add(, ));
Console.WriteLine("secondResult call :" + secondResult.Add(, )); }
catch (RuntimeBinderException ex)
{
Console.WriteLine(ex.Message);
} Console.ReadLine();
} static int callCount = ;
static dynamic GetValue()
{
if (callCount++ == )
return new MyClass1();
return new MyClass2();
}
} class MyClass1
{
public int Add(int op1, int op2)
{
return op1 + op2;
}
} class MyClass2
{ } }

 6.高级方法参数:可选参数和命名参数

可选参数

假如一个方法有大量的参数,有些参数并不是每次调用都需要传过去的,这意味着需要一种方式指定缺失的参数,否则在代码中会出现许多空值,比如

RmoteCall(var1,var2,null,null,null,null,null)

在理想情况下,这个RmoteCall方法应该有多个重载版本,其中一个有两个参数,但这样就需要维护更多的代码。

RmoteCall(var1,var2)

使用可选参数可以解决这个问题,可选参数的定义方式是在方法定义时,在参数后面赋默认值

public List<string>GetWords(string sentence,bool capitalizeWords=false)
{
//....
}

可选参数必须放在参数列表末尾,在所有必选参数后面

命名参数

假如有几个可选参数,我们只想给其中一个可选参数赋值,就可以用到命名参数,在调用方法时,指定参数的名和对应的值

public List<string>GetWords(string sentence,bool capitalizeWords=false, bool var1 =false)
{
//....
} //给最后一个可选参数赋值
GetWords("....",var1:true);

 7.扩展方法

我们知道类型的操作是封装在数据类型里面的,使用扩展方法可以扩展类型的功能,而不修改类型本身。

创建一个扩展方法需要以下步骤:

1)创建一个非泛型静态类;

2)创建一个静态方法,该方法必须包含一个参数,该参数放在所有参数前面,用this关键字和类型符修饰,表示调用扩展方法的类型实例;

3)在使用扩展方法的地方用using语句导入包含扩展方法的类的名称空间;

4)通过扩展类型的一个实例调用方法,与调用该扩展类型的其他方法一样。

下面是给string类添加扩展方法的一个例子

namespace ConsoleApplication1
{
static class WordProgressor
{
public static List<string> GetWords(this string sentence, bool capitalizeWords = false, bool reverseOrder = false, bool reverseWords=false)//扩展方法
{
List<string> words = new List<string>(sentence.Split(' '));
if (capitalizeWords)
words = CapitalizeWords(words);
if (reverseOrder)
words = ReverseOrder(words);
if (reverseWords)
words = ReverseWords(words);
return words;
} public static List<string> CapitalizeWords(List<string> words)
{
List<string> capititalzieWords = new List<string>();
foreach (string word in words)
{
if (word.Length == )
capititalzieWords.Add(word[].ToString().ToUpper() );
else if(word.Length >)
capititalzieWords.Add(word[].ToString().ToUpper() + word.Substring());
} return capititalzieWords;
} public static List<string> ReverseOrder(List<string> words)
{
List<string> reverseOrder = new List<string>();
for (int i = words.Count - ; i >= ; i--)
{
reverseOrder.Add(words[i]);
} return reverseOrder;
} public static List<string> ReverseWords(List<string> words)
{
List<string> reverseWords = new List<string>();
foreach (string word in words)
{
reverseWords.Add(ReverseWord(word));
}
return reverseWords;
} public static string ReverseWord(string word)
{
StringBuilder sb = new StringBuilder();
for (int i = word.Length - ; i >= ; i--)
{
sb.Append(word[i]);
}
return sb.ToString();
} public static string ToStringReversed(this Object inputObject)//扩展方法
{
return ReverseWord(inputObject.ToString());
} public static string AsSentence(this List<string> words)//扩展方法,该方法扩展的类型是List<string>,所以只有该类型才能调用
{
StringBuilder sb = new StringBuilder();
for (int i = ; i < words.Count; i++)
{
sb.Append(words[i]);
if (i != words.Count - )
sb.Append(' ');
}
return sb.ToString();
}
} class Program
{ static void Main(string[] args)
{
string sourceString = "To go beyond is a wrong as to fall short."; Console.WriteLine(sourceString.ToStringReversed());
Console.WriteLine(sourceString.GetWords(capitalizeWords: true).AsSentence());
Console.ReadLine();
} } }

23.C# 语言的改进的更多相关文章

  1. GO学习-(23) Go语言操作MySQL + 强大的sqlx

    Go语言操作MySQL MySQL是业界常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库. Go操作MySQL 连接 Go语言中的database/sql包提供了保证SQL或类SQL数据 ...

  2. 2-3 R语言基础 矩阵和数组

    #矩阵Matrix  三个参数:内容(可省),行数,列数 > x <- matrix(1:6,nrow = 3,ncol = 2) #第一个是内容,第二个,第三个是行列> x[1,2 ...

  3. Rust 2017 调查报告:学习曲线是最大痛点(最大的问题是这门语言太偏底层了,现在做底层的少了。还有C这个绕不过去的存在)

    Rust 官方在社区上做了一次调查,以了解用户如何看待 Rust 的发展.调查共收到 5368 份回复,其中有 大约 2/3 的是 Rust 用户,剩下的 1/3 是非 Rust 用户,调查结果如下. ...

  4. 【GoLang】转载:我为什么放弃Go语言,哈哈

    我为什么放弃Go语言 作者:庄晓立(Liigo) 日期:2014年3月 原创链接:http://blog.csdn.NET/liigo/article/details/23699459 转载请注明出处 ...

  5. C语言不是C++的严格子集

    C语言是C++的子集吗?C++是在C语言的基础上扩展而来并包含所有C语言的内容吗? 回复: 从实用角度讲,C++属于C语言的一个超集,基本上兼容ANSI C.但是从编译角度上讲,C语言的有些特性在C+ ...

  6. 我为什么放弃Go语言

    有好几次,当我想起来的时候,总是会问自己:我为什么要放弃Go语言?这个决定是正确的吗?是明智和理性的吗?事实上我一直在认真思考这个问题. 开门见山地说,我当初放弃Go语言(golang),就是由于两个 ...

  7. c语言,变长数组

    下面这个结构体,可以在malloc的时候指定数据data的长度,这样的形式就是变长数组:typedef struct{ int data_len; char data[0];//或char data[ ...

  8. java语言与jvm虚拟机简介

    一.java语言 1.1 支持面向对象编程oop 强调支持,因为java同样可以面向过程编程. oop的三大特性是:封装.继承.多态. 封装主要针对成员变量而言,oop的思想要求成员变量均为私有,不应 ...

  9. 驳2B文 "我为什么放弃Go语言"

      此篇文章流传甚广, 其实里面没啥干货, 而且里面很多观点是有问题的. 这个文章在 golang-china 很早就讨论过了. 最近因为 Rust 1.0 和 1.1 的发布, 导致这个文章又出来毒 ...

随机推荐

  1. SQL允许脏读WITH(NOLOCK)

    使用WIHT(NOLOCK)有利也有弊,所以在决定使用之前,你一定需要了解清楚WITH(NOLOCK)的功能和缺陷,看其是否适合你的业务需求,不要觉得它能提升性能,稀里糊涂的就使用它. --事务未提交 ...

  2. scrapy_redis 相关: 查看保存的数据

    0.参考资料 https://redis.io/topics/data-types-intro An introduction to Redis data types and abstractions ...

  3. James Munkres Topology: Theorem 16.3

    Theorem 16.3 If \(A\) is a subspace of \(X\) and \(B\) is a subspace of \(Y\), then the product topo ...

  4. Excel—单元格引用

    EXCEL的引用有3种:相对引用.绝对引用.混合引用 相对引用.绝对引用比较简单,就是要么拖拽后变,要么拖拽后不变 混合引用有点难度,凡是需要向右拖拽再向下拖拽的记住一定是混合引用 要将拖拽后依然不变 ...

  5. Tomcat目录结构详解

    1.bin: 该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat6.exe.tomcat6w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口 ...

  6. RecyclerView滑动到指定位置,并置顶

    一般我们用 mRecycleview.smoothScrollToPosition(0)滑动到顶部,具有滚动效果,但是如果我们想滚动到任意指定位置,那么smoothScrollToPosition() ...

  7. Java开发人员必须掌握的Linux命令-学以致用(5)

    ================================================= 人工智能教程.零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助! 点击查看高清无码教程 == ...

  8. Linux-vi编辑器简单使用(保证存活)

    vi编辑器基本模式 命令行模式(command mode) 光标移动.复制粘贴.删除 插入模式(insert mode) 文字输入 底行模式(last line mode) 保存.退出 模式转换 co ...

  9. 友元(friend)

    1.友元类的关系不能传递和继承 ...待续

  10. 红帽 Red Hat Linux相关产品iso镜像下载【百度云】【更新7.2】

    RedHat Enterprise Server 6.7 for i386 Boot Disk:rhel-server-6.7-i386-boot.iso SHA-256 Checksum: 798d ...