c# - ToCharArray 和 ToArray 之间的区别

标签 c# arrays string

ToCharArrayToArray 有什么区别

string mystring = "abcdef";

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

结果好像是一样的

最佳答案

string.ToCharArray() 是字符串类的成员。

string.ToArray()实际上正在使用 a ToArray() extension of IEnumerable<T> , 利用 string工具 IEnumerable<char> .

两者中,string.ToCharArray()可能会更高效。

来自 C# 引用源,string.ToCharArray() 的实现是:

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;
}

同样来自 C# 引用源,IEnumerable<T>.ToArray() 的实现是:

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;
    }
}        

如您所见,这要复杂得多!

为什么不 IEnumerable<T>.ToArray()使用优化路径?

还有一件事我们需要解释。

如果您检查 Buffer<T> 的执行情况你会看到这个优化:

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

您可以合理地问为什么不采用该路径?如果是,这将是对 string.ToArray() 的一个很好的优化。 .

嗯,答案很简单:A string没有实现 ICollection<T>因此 source as ICollection<TElement>将返回 null,并且该优化将不会完成。

更糟糕的是,通过 Buffer<T> 的非优化路径将使用 string枚举器,实现如下:

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);
    }
}    

这带来了另一个层面的低效率。

这个故事的寓意

切勿使用 IEnumerable<char>.ToArray()而不是 string.ToCharArray() !

关于c# - ToCharArray 和 ToArray 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37139053/

相关文章:

c# - C#中如何判断一个数组是否存在?

ruby - 在 Ruby 中提取 URL(到数组)

java - 在 Java 中用 "$"替换包含 "\$"的字符串

C# 字符串等于不能正常工作

c# - 如何记录异步方法的异常?

arrays - 在 Golang 中获取指针数组的长度

java - 删除除连字符之外的所有特殊字符

c# - 当窗口打开时,如何将数据模板化的文本框集中在窗口中 I​​temsControl 的第一个元素中? (C#, WPF)

c# - 如何使用c#在word中插入脚注

javascript - 给定一个多维数组,返回一个包含对 Angular 线总和的数组