首页 > 代码库 > 数组之间如何进行转换

数组之间如何进行转换

分析问题

  在程序中,类型转换无处不在,数组类型也不例外。对于普通的类型,子类对象可以隐式地转换为父类类型,所有的数组类型都继承自System.Array类型,不存在相互间的关系,但隐式转换仍然被允许,其机制如下:

  1、包含值类型项目的数组不能隐式地转换成其他任何类型。

  2、两个数组类型能够相互转换的一个前提是两者维数相同。

  在满足上述两个前提下,源数组的项目类型必须存在一个隐式或者显式的转换到目标数组的项目类型。

  下面的一些代码说明了转换的机制:

  //编译成功

  string[] sz={"a","a","a"};

  object[] oz=sz;

  //编译失败,值类型项目的数组不能被转换

  int[] sz={1,2,3};

  object[] oz=sz;

  //编译失败,两者维数不同

  string[,] sz={{"a","b"},{"a","b"}};

  object[] oz=sz;

注意

  隐式转换数组类型并不是一个好方法,当一个object[]的引用指向一个数组是,任何对数组项目的合法操作都会产生性能影响,而任何类型不符合的操作都会在运行时抛出一个ArrayTypeMismatchException异常。

  除了类型上的转换,有时候程序员还会遇到内容转换的需求。举例来说,在一系列的用户界面操作后,系统的后台可能得到一个DateTime的数组,而现在的任务是把它们存储到数据库中,而数据访问层提供的接口直接受string[]的参数,这时候程序员要做的就是把DateTime[]从内容上转换为string[]对象。当然,惯例的做法是遍历整个源数组,逐一地转换每个对象并且将其放入一个目标数组项目类型的容器之中,最后再生成目标数组,这样的做法在程序的灵活性和性能上都比不上Array.ConvertAll方法。后者提供了一个简便的转换数组间内容的接口,程序员需要指定源数组的项目类型、对象数组的项目类型和转换的算法,该方法就能高效地完成转换的工作。以下代码展示了具体的使用方法。

 

using System;using System.Collections.Generic;namespace Test{    class ArrayConvert    {        static void Main()        {            string[] times = { "2008-1-1", "2008-1-2", "2008-1-3" };            //使用不同的方法转换            DateTime[] result1 = OneByOne(times);            DateTime[] result2 = ConvertAll(times);            //结果是相同的            foreach (var item in result1)            {                Console.WriteLine(item.ToString("yyyy-MM-dd"));            }            Console.Write("\r\n");            foreach (var item in result2)            {                Console.WriteLine(item.ToString("yyyy-MM-dd"));            }            Console.Read();        }        //逐个手动转换        private static DateTime[] OneByOne(string[] times)        {            List<DateTime> result = new List<DateTime>();            foreach (var item in times)            {                result.Add(DateTime.Parse(item));            }            return result.ToArray();        }        //使用Array.ConvertAll方法        private static DateTime[] ConvertAll(string[] times)        {            return Array.ConvertAll(times, new Converter<string, DateTime>(ArrayConvert.DateTimeToString));        }        //转换算法        private static DateTime DateTimeToString(string time)        {            return DateTime.Parse(time);        }                 }}

  以上代码展示了两种内容转换的区别,两者实现了相同的功能,但Array.ConvertAll不需要程序手动遍历数组,也不需要生成一个临时的容器对象,更加突出的优势是,它可以接受一个动态的算法作为转换依据。这个算法可以以一个方法的形式传入,也可以以一个委托的形式传入,关于委托的概念在后面章节中会有叙述。这样的机制保证了Array.ConvertAll拥有了相当高的程序灵活性和运行性能。

答案

  数组类型在符合条件的情况下可以进行隐式的转换,条件包括:数组维数必须相同;目标项目类型和源项目类型必须存在隐式或者显式转换关系;源数组的项目类型不是值类型。

  数组类型可以通过Array.ConvertAll方法进行内容转换,该方法需要使用者提供一个转换算法,以委托或者方法的形式传入Array.ConvertAll方法中。