• 23.C# 语言的改进


    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 = 8;

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

    Curry test = new Curry { MainIngredient = "painr tikka", Style = "jal", Speciness = 8 };
        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(8) { MainIngredient = "painr tikka", Style = "jal"};

     2.集合初始化器

    List<int> primes = new List<int>() { 1, 3, 5, 7, 9 };

    集合初始化器会默认调用集合的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=5
                    };

    匿名类型的特征是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=5
                    },
                       new { 
                        MainIngredient = "Lamb",
                        Style="Dhansak",
                        Spicinesss=5
                    },
                       new { 
                        MainIngredient = "Chicken",
                        Style="Dhansak",
                        Spicinesss=5
                    }
                    };
    
                    Console.WriteLine(curries[0].Equals(curries[1]));
                    Console.WriteLine(curries[0].Equals(curries[2]));
                    Console.WriteLine(curries[0].GetHashCode());
                    Console.WriteLine(curries[1].GetHashCode());
                    Console.WriteLine(curries[2].GetHashCode());
                    Console.WriteLine(curries[0] == curries[1]);
                    Console.WriteLine(curries[0] == curries[2]);
    
                }
                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", 2, 3));

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

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

    动态查找方法可以根据变量的具体类型,动态的查找该类型是否有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(1, 2));
                    Console.WriteLine("secondResult call :" + secondResult.Add(1, 2));
    
                }
                catch (RuntimeBinderException ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                Console.ReadLine();
            }
    
            static int callCount = 0;
            static dynamic GetValue()
            {
                if (callCount++ == 0)
                    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 == 1)
                        capititalzieWords.Add(word[0].ToString().ToUpper() );
                    else if(word.Length >1)
                        capititalzieWords.Add(word[0].ToString().ToUpper() + word.Substring(1));
                }
    
                return capititalzieWords;
            }
    
            public static List<string> ReverseOrder(List<string> words)
            {
                List<string> reverseOrder = new List<string>();
                for (int i = words.Count - 1; i >= 0; 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 - 1; i >= 0; 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 = 0; i < words.Count; i++)
                {
                    sb.Append(words[i]);
                    if (i != words.Count - 1)
                        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();
            }
    
        }
    
    }
    View Code

  • 相关阅读:
    【java8】慎用java8的foreach循环(作废)
    【Java并发系列03】ThreadLocal详解
    【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
    【Java并发系列02】Object的wait()、notify()、notifyAll()方法使用
    【Java并发系列01】Thread及ThreadGroup杂谈
    java安全管理器SecurityManager入门
    【DWR系列06】- DWR日志及js压缩
    时间插件
    springMVC中Restful支持
    面向接口编程
  • 原文地址:https://www.cnblogs.com/lidaying5/p/10655802.html
Copyright © 2020-2023  润新知