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. Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  2. git合并分支

    源分支向向目标分支上合并.将fix分支向develop分支上合并

  3. POJ 1201 Intervals (经典) (差分约束)

    <题目链接> 题目大意:给你$n$段区间,$a_i,b_i,c_i$ 表示在 $[a_i,b_i]$ 区间内至少要选择$c_i$个点.现在问你在满足这n个条件的情况下,最少要选多少个点? ...

  4. Android-Layer list

    Android-Layer list 学习自: KEEGAN小钢 原文链接 : (https://keeganlee.me/post/android/20150909) 使用layer-list 可以 ...

  5. 杭电1532----Drainage Ditches『最大流』

    /* 网络流的最大流问题 刚学习Dinic算法.模版题 */ #include <cstring> #include <cstdio> #include <queue&g ...

  6. [R]dplyr及ggplot2中的变量引用列的问题

    问题描述: 存在这么一个场景,当需要动态选择列作为dplyr或ggplot2的输入时,列名的指定会出现问题. 以iris举例: # 以iris dataset为例 colnames <- c(& ...

  7. Linux中Buffer和Cache的区别

    1. Cache:缓存区,是高速缓存,是位于CPU和主内存之间的容量较小但速度很快的存储器,因为CPU的速度远远高于主内存的速度,CPU从内存中读取数据需等待很长的时间,而  Cache保存着CPU刚 ...

  8. 03-Python入门学习-Python基础

    一.与用户交互 1.什么是与用户交互 程序等待用户输入一些数据,然后程序执行完毕后为用户反馈信息 2.为何程序要与用户交互 为了让计算机能够像人一样与用户的交互 3.如何用 在python3中:inp ...

  9. c#关键字和常用类型表快查

    类型 字节 取值范围 说明 bool 1 true/false/null 布尔类型 char 2 0x0000~0xffff Unicode 16 位字符 byte 1 0~255 无符号的 8 位整 ...

  10. [LeetCode] Sliding Puzzle 滑动拼图

    On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square repre ...