欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

using static 声明

程序员文章站 2024-03-23 14:12:40
...

许多实际的扩展可以通过扩展方法来实现,比如前面的Use扩展方法或前面介绍的用于LINQ的许多扩展方法。在本书后面的许多章节中还将介绍.NET提供的许多扩展方法。

并非所有实际的扩展都有可以扩展的类型。对于某些场景,简单的静态方法比较适合。为了更容易调用这些方法,可以使用using static 声明除去类名。

例如,如果打开了System.Console

using static System.Console;

可以把下面的代码

Console.WriteLine("Hello World!");

改为

WriteLine("Hello World!");

在使用此声明之后,就可以使用类Console的所有静态成员,如WriteLine、Write、ReadLine、Read、Beep等,而不需要编写Console类。只需要确保再打开其他类的静态成员时不要陷入冲突,或者在使用静态方法时不要使用基类的方法。

下面看一个实际的例子。高阶函数以函数作为参数,或者返回一个函数,或者返回两个函数。在处理函数时,可以将两个函数合并到一个函数中。

为此可以使用Compose方法,如下面的代码片段所示:

     class FunctionalExtensions
    {
        public static Func<T1,TResult> Compose<T1,T2,TResult>(
            Func<T1,T2> f1,Func<T2,TResult> f2)=>a=>f2(f1(a));
    }

该泛型方法定义了三个类型参数和两个委托类型Func的参数。请记住,委托Func<T,Result>引用了一个带有单个参数的方法。其返回类型可以是不同的类型。Compose方法接受两个Func参数,把两个方法组合到一个方法中。传递给Compose的第一个方法(f1)可以有两个不同的类型,一个用于输入(T1),另一个用于输出(T2),而传递的第二个方法(f2)所需要的输入类型(T2)与第一个方法的输出类型(T2)相同,并且可以有不同的输出类型(TResult)。Compose方法本身返回一个Func委托,其输入类型与第一个方法相同(T1),输出类型与第二个方法相同(TResult)。实现可能看起来有点可怕,因为后面跟着连续两个lambda操作符。理解了方法返回的内容(一个方法)时,这个构造就将变得清晰。返回的方法是Func<T1,TResult>。在第一个lambda操作符之后,=>f2(f1(a)); 定义了这个方法。变量的类型为T1,返回的方法类型为TResult,与f2返回的结果类型相同,f2以输入作为参数接收f1。

要使用Compose方法,首先创建两个委托f1和f2,在输入中添加1或2。这些委托会与Compose方法相结合。由于using static 声明打开了类FunctionalExtensions的静态成员,所以可以不使用类名来调用Compose方法。在使用Compose方法创建f3之后,就调用f3方法:

using System;
using static System.Console;
using static usingStatic声明.FunctionalExtensions;

namespace usingStatic声明
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int,int> f1 = x=>x+1;
            Func<int,int> f2 = x=>x+2;
            Func<int,int> f3 = Compose(f1,f2);
            var x1 = f3(39);
            WriteLine(x1);
        }
    }

      class FunctionalExtensions
    {
        public static Func<T1,TResult> Compose<T1,T2,TResult>(
            Func<T1,T2> f1,Func<T2,TResult> f2)=>a=>f2(f1(a));
    }
}

写入控制台的结果当然是42。

42

声明Compose方法时,参数类型可以在输入和输出之间有所不同。在下面的代码片段中,传递给Compose方法的第一个方法接收一个字符串。并返回Person对象;第二个方法接收Person并返回一个字符串。如果编译器不能从变量和返回类型中识别参数类型,就必须指定具体的委托类型,方法是接收字符串并返回一个Person。只有变量名,并不能帮助编译器确定它的类型。通过传递给Compose方法的第二个方法,显示,输入的类型与第一个方法返回的类型相同,因此不需要指定类型。在调用Compose方法之后,变量greetPerson是两个输入方法的组合:

            var greetPerson = Compose(new Func<string,Person>(name=>new Person(name)),
            person=>$"Hello,{person.FirstName}");
            WriteLine(greetPerson("Mario Andretti"));

在WriteLine方法中使用字符串Mario Andretti调用greetPerson方法,将字符串Hello,Marro写入控制台。

完整代码:

using System;
using static System.Console;
using static usingStatic声明.FunctionalExtensions;

namespace usingStatic声明
{
    class Program
    {
        static void Main(string[] args)
        {
            // Func<int,int> f1 = x=>x+1;
            // Func<int,int> f2 = x=>x+2;
            // Func<int,int> f3 = Compose(f1,f2);
            // var x1 = f3(39);
            // WriteLine(x1);

            var greetPerson = Compose(new Func<string,Person>(name=>new Person(name)),
            person=>$"Hello,{person.FirstName}");
            WriteLine(greetPerson("Mario Andretti"));
        }
    }

      class FunctionalExtensions
    {
        public static Func<T1,TResult> Compose<T1,T2,TResult>(
            Func<T1,T2> f1,Func<T2,TResult> f2)=>a=>f2(f1(a));
    }

        public class Person
    {
        public Person(string name)=>name.Split(' ').ToStrings(out _firstName,out _lastName);
        private string _firstName;
        public string FirstName
        {
            get=>_firstName;
            set=>_firstName = value;
        }
        private string _lastName;
        public string LastName
        {
            get=>_lastName;
            set=>_lastName = value;
        }
        public override string ToString()=>$"{FirstName} {LastName}";
    }
    public static class StringArrayExtensions
    {
        public static void ToStrings(this string[] values,out string value1,out string value2)
        {
            if(values == null) throw new ArgumentNullException(nameof(values));
            if(values.Length != 2) throw new IndexOutOfRangeException("only arrays with 2 values allowed");
            value1  = values[0];
            value2 = values[1];
        }
    }
}