Difference between ToCharArray and ToArray

前端 未结 3 2064

What is the difference between ToCharArray and ToArray

string mystring = \"abcdef\";

char[] items1 = mystring.ToCharArray();
char[         


        
相关标签:
3条回答
  • 2020-12-09 04:58

    string.ToCharArray() is a member of the string class.

    string.ToArray() is actually using a ToArray() extension of IEnumerable<T>, taking advantage of the fact that string implements IEnumerable<char>.

    Of the two, string.ToCharArray() is likely to be more performant.

    From the C# reference source, the implementation of string.ToCharArray() is:

    unsafe public char[] ToCharArray() {
        // <
        int length = Length;
        char[] chars = new char[length];
        if (length > 0)
        {
            fixed (char* src = &this.m_firstChar)
                fixed (char* dest = chars) {
                    wstrcpy(dest, src, length);
                }
        }
        return chars;
    }
    

    Also from the C# reference source, the implementation of IEnumerable<T>.ToArray() is:

    public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source) {
        if (source == null) throw Error.ArgumentNull("source");
        return new Buffer<TSource>(source).ToArray();
    }
    
    ...
    
    struct Buffer<TElement>
    {
        internal TElement[] items;
        internal int count;
    
        internal Buffer(IEnumerable<TElement> source) {
            TElement[] items = null;
            int count = 0;
            ICollection<TElement> collection = source as ICollection<TElement>;
            if (collection != null) {
                count = collection.Count;
                if (count > 0) {
                    items = new TElement[count];
                    collection.CopyTo(items, 0);
                }
            }
            else {
                foreach (TElement item in source) {
                    if (items == null) {
                        items = new TElement[4];
                    }
                    else if (items.Length == count) {
                        TElement[] newItems = new TElement[checked(count * 2)];
                        Array.Copy(items, 0, newItems, 0, count);
                        items = newItems;
                    }
                    items[count] = item;
                    count++;
                }
            }
            this.items = items;
            this.count = count;
        }
    
        internal TElement[] ToArray() {
            if (count == 0) return new TElement[0];
            if (items.Length == count) return items;
            TElement[] result = new TElement[count];
            Array.Copy(items, 0, result, 0, count);
            return result;
        }
    }        
    

    As you can see, that's a LOT more complicated!

    Why doesn't IEnumerable<T>.ToArray() use the optimised path?

    There's one other thing we need to explain.

    If you inspect the implementation of Buffer<T> you'll see this optimisation:

    ICollection<TElement> collection = source as ICollection<TElement>;
    if (collection != null) {
        count = collection.Count;
        if (count > 0) {
            items = new TElement[count];
            collection.CopyTo(items, 0);
        }
    }    
    

    You could reasonably ask why that path isn't taken? If it was, this would be a good optimisation for string.ToArray().

    Well, the answer is simply: A string doesn't implement ICollection<T> and therefore source as ICollection<TElement> will return null, and that optimisation will not be done.

    Even worse, the non-optimised path through Buffer<T> will use the string enumerator, which is implemented as follows:

    public sealed class CharEnumerator : IEnumerator, ICloneable, IEnumerator<char>, IDisposable 
    {
        private String str;
        private int index;
        private char currentElement;
    
        internal CharEnumerator(String str) {
            Contract.Requires(str != null);
            this.str = str;
            this.index = -1;
        }
    
        public Object Clone() {
            return MemberwiseClone();
        }
    
        public bool MoveNext() {
            if (index < (str.Length-1)) {
                index++;
                currentElement = str[index];
                return true;
            }
            else
                index = str.Length;
            return false;
    
        }
    
        public void Dispose() {
            if (str != null)
                index = str.Length;
            str = null;
        }
    
        /// <internalonly/>
        Object IEnumerator.Current {
            get {
                if (index == -1)
                    throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
                if (index >= str.Length)
                    throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));                        
    
                return currentElement;
            }
        }
    
        public char Current {
            get {
                if (index == -1)
                    throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
                if (index >= str.Length)
                    throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));                                            
                return currentElement;
            }
        }
    
        public void Reset() {
            currentElement = (char)0;
            index = -1;
        }
    }
    
    
    ICollection<TElement> collection = source as ICollection<TElement>;
    if (collection != null) {
        count = collection.Count;
        if (count > 0) {
            items = new TElement[count];
            collection.CopyTo(items, 0);
        }
    }    
    

    This introduces a whole other level of inefficiency.

    The moral of this story

    Never use IEnumerable<char>.ToArray() instead of string.ToCharArray()!

    0 讨论(0)
  • 2020-12-09 05:02

    If we are talking about converting strings to letters, the ToCharArray () function is faster than ToArray ()

    0 讨论(0)
  • 2020-12-09 05:10

    ToCharArray method:

    ToCharArray method to extract the characters in a string to a character array. It then displays the original string and the elements in the array.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          String s = "AaBbCcDd";
          var chars = s.ToCharArray();
          Console.WriteLine("Original string: {0}", s);
          Console.WriteLine("Character array:");
          for (int ctr = 0; ctr < chars.Length; ctr++)
             Console.WriteLine("   {0}: {1}", ctr, chars[ctr]);
       }
    }
    

    ToArray method :

    ToArray method of the List class that act on ranges.

    using System;
    using System.Collections.Generic;
    
    public class Example
    {
        public static void Main()
        {
            string[] input = { "Brachiosaurus", 
                               "Amargasaurus", 
                               "Mamenchisaurus" };
    
            List<string> dinosaurs = new List<string>(input);
    
            Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
    
            Console.WriteLine();
            foreach( string dinosaur in dinosaurs )
            {
                Console.WriteLine(dinosaur);
            }
    
            Console.WriteLine("\nAddRange(dinosaurs)");
            dinosaurs.AddRange(dinosaurs);
    
            Console.WriteLine();
            foreach( string dinosaur in dinosaurs )
            {
                Console.WriteLine(dinosaur);
            }
    
            Console.WriteLine("\nRemoveRange(2, 2)");
            dinosaurs.RemoveRange(2, 2);
    
            Console.WriteLine();
            foreach( string dinosaur in dinosaurs )
            {
                Console.WriteLine(dinosaur);
            }
    
            input = new string[] { "Tyrannosaurus", 
                                   "Deinonychus", 
                                   "Velociraptor"};
    
            Console.WriteLine("\nInsertRange(3, input)");
            dinosaurs.InsertRange(3, input);
    
            Console.WriteLine();
            foreach( string dinosaur in dinosaurs )
            {
                Console.WriteLine(dinosaur);
            }
    
            Console.WriteLine("\noutput = dinosaurs.GetRange(2, 3).ToArray()");
            string[] output = dinosaurs.GetRange(2, 3).ToArray();
    
            Console.WriteLine();
            foreach( string dinosaur in output )
            {
                Console.WriteLine(dinosaur);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题