string.substring vs string.take

Wil*_*ams 23 c# substring

如果您只想获取字符串的一部分,则主要使用子字符串方法.这有一个缺点,你必须首先测试字符串的长度,以避免错误.例如,您希望将数据保存到数据库中,并希望将值剪切为前20个字符.

如果你执行temp.substring(0,20)但temp只保存10个字符,则抛出异常.

我看到有两种解决方案:

  1. 测试长度,并在需要时执行子串
  2. 使用扩展方法Take

        string temp = "1234567890";
        var data= new string( temp.Take(20).ToArray());
        --> data now holds "1234657890"
    
    Run Code Online (Sandbox Code Playgroud)

当使用Take方法时,在速度或内存使用方面是否有任何缺点.好处是您不必编写所有if语句.

Mat*_*son 24

如果你发现自己这么做了,为什么不写一个扩展方法呢?

例如:

using System;

namespace Demo
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("123456789".Left(5));
            Console.WriteLine("123456789".Left(15));
        }
    }

    public static class StringExt
    {
        public static string Left(this string @this, int count)
        {
            if (@this.Length <= count)
            {
                return @this;
            }
            else
            {
                return @this.Substring(0, count);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*lba 12

正如Henk Holtermand所说,Take()创造一个IEnumerator,然后你需要这个ToArray()电话.

因此,如果性能在您的应用程序中很重要,或者您将在流程中多次执行子字符串,则性能可能会成为问题.

我写了一个示例程序来准确地Take()确定结果的方法有多慢:

经过千万次测试:

  • 执行子串的时间:266毫秒
  • 执行操作的时间:1437毫秒

以下是代码:

    internal const int RETRIES = 10000000;

    static void Main(string[] args)
    {
        string testString = Guid.NewGuid().ToString();

        long timeSubstring = MeasureSubstring(testString);
        long timeTake = MeasureTake(testString);

        Console.WriteLine("Time substring: {0} ms, Time take: {1} ms",
            timeSubstring, timeTake);
    }

    private static long MeasureSubstring(string test)
    {
        long ini = Environment.TickCount;

        for (int i = 0; i < RETRIES; i++)
        {
            if (test.Length > 4)
            {
                string tmp = test.Substring(4);
            }
        }

        return Environment.TickCount - ini;
    }

    private static long MeasureTake(string test)
    {
        long ini = Environment.TickCount;

        for (int i = 0; i < RETRIES; i++)
        {
            var data = new string(test.Take(4).ToArray());
        }

        return Environment.TickCount - ini;
    }
Run Code Online (Sandbox Code Playgroud)


ken*_*n2k 6

首先,我不想回答(因为已经有有效的答案),但是我想添加一些不适合作为注释的内容:

您正在谈论性能/内存问题。对。正如其他人所说,string.SubString之所以更有效,是因为它是如何内部优化的以及因为LINQ是如何工作的string.Take()(字符的枚举等)。

没有人说的是,这种情况的主要缺点Take()是,它完全破坏了子字符串的简单性。正如Tim所说,要获得所需的实际字符串,您必须编写:

string myString = new string(temp.Take(20).ToArray());
Run Code Online (Sandbox Code Playgroud)

该死的……这比(相比于Matthew的扩展方法)更难理解:

string myString = temp.Left(20);
Run Code Online (Sandbox Code Playgroud)

LINQ非常适合许多用例,但如果没有必要,则不应使用。甚至一个简单的循环有时也比LINQ更好(例如,更快,更易读/更易理解),因此请想象一个简单的子字符串...

总结有关您的情况的LINQ:

  • 表现较差
  • 可读性较差
  • 不太容易理解
  • 需要LINQ(例如,不适用于.Net 2.0)