非特殊情况,数组越界

时间:2013-07-02 10:04:51

标签: c# arrays exception split

我明白我想要做的事情有点像黑客,但它仍然很有趣。

我的情况很可能是数组可能没有我期望的那么多项目。

这是概念:

namespace TESTAPP
{
    class Program
    {
        static void Main(string[] args)
        {
            string derp = "foooooo";
            //The split is important, you might not have the character there to split by
            Writer(derp.Split('x')[0] ?? ".");
            Writer(derp.Split('x')[1] ?? ".");
        }

        private static void Writer(string writeme)
        {
            Console.WriteLine(writeme ?? "..");
        }
    }
}

当然,在执行上述打印时我并不太感到惊讶:

foooooo

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
at TESTAPP.Program.Main(String[] args) in [snip]\TESTAPP\Program.cs:line 15

我应该如何逻辑地处理这种情况? try/catch块看起来有点矫枉过正。

9 个答案:

答案 0 :(得分:2)

首先,您只需要拆分一次,而不是再次拆分每个部分:

string derp = "foooooo";
string[] parts = derp.Split('x');
// parts == { "foooooo" }
// parts.Length == 1

现在您有一个包含许多部分的数组,因此您只需在访问每个部分之前检查Length属性:

Writer(parts.Length > 0 ? parts[0] : ".");
Writer(parts.Length > 1 ? parts[1] : ".");
Writer(parts.Length > 2 ? parts[2] : ".");
Writer(parts.Length > 3 ? parts[3] : ".");
Writer(parts.Length > 4 ? parts[4] : ".");

for (int i = 0; i < 5; i++)
{
    Writer(parts.Length > i ? parts[i] : ".");
}

输出:

foooooo..
...
...
...
...

答案 1 :(得分:1)

在这个具体的例子中..迭代结果:

foreach (var item in derp.Split('x'))
    Writer(item);

如果还有其他具体案例......那么这显然可能不符合您的要求。

答案 2 :(得分:1)

只需适当更改条件,不要尝试全部内联:

var split = derp.Split('x');
Writer(split.Length >= 2 ? split[1] : ".");

如果输入中存在大量此类条件并且每个条件默认为不同的值,则可以预先调整数组的大小:

var split = derp.Split('x');
Array.Resize(ref split, 2);

Writer(split[1] ?? "."); // this is now safe

请注意,上面的内容看起来很糟糕,因为[1]没有说明该数组元素的内容,因此默认为"."的原因可能并不明显。

答案 3 :(得分:1)

定义GetOrDefault扩展方法,如下所示:

// If you need this method to work with collections or even IEnumerables,
// you can change implementation to get the count differently.
// This should be sufficient for arrays, though:
static T GetOrDefault(this T[] items, int index) {
    return items.Length > index ? items[index] : default(T);
}

现在您可以按如下方式使用此方法:

Writer(derp.Split('x').GetOrDefault(0) ?? ".");
Writer(derp.Split('x').GetOrDefault(1) ?? ".");

答案 4 :(得分:1)

问题在于derp.Split('x')[1]

您无法检查[1]元素是否为空,因为它不存在。想象一下情况: 我给你一个桶,把'fooooo'放进去。 然后我问你,"Is the second bucket empty?"。 你不能说"yes",你不能说"no"。桶只是不存在,所以你会说"ArrayIndexOutOfBoundsException" - 没有第二个桶,所以我无法检查它是否为空;)

答案 5 :(得分:0)

如果不是特殊情况,请不要使用例外,如果可以的话。

在这个具体案例中,你可以避免使用异常并只使用简单的边界控制,就像(只是一个例子):

var splitted = derp.Split('x');
if(splitted.Length > 1) {
   Writer(derp.Split('x')[0] ?? ".");
   Writer(derp.Split('x')[1] ?? ".");
}

答案 6 :(得分:0)

您应该使用if声明:

var result = derp.Split('x');
if (result.Length > 0)
    Writer(result[0]);
else
    //...

答案 7 :(得分:0)

迭代Split

返回的数组
var splitOutput = derp.Split('x');

foreach (var s in splitOutput)
     Writer(s);
}

答案 8 :(得分:0)

分而治之。

如果您希望该值存在:

static void Main(string[] args)
{
    string derp = "foooooo";
    var parts = derp.Split('x');
    if (parts.Length != 2)
        throw new InvalidOperationException("Expected string to have to dot X delimited values. Actual string: " + derp);

    Writer(derp.Split('x')[0] ?? ".");
    Writer(derp.Split('x')[1] ?? ".");
}

如果您希望缺少这些值:

static void Main(string[] args)
{
    string derp = "foooooo";
    var parts = derp.Split('x');

    if (parts.Length > 0)
        Writer(parts[0]);
    else
        Writer(".");

    if (parts.Length > 1)
        Writer(parts[1]);
    else
        Writer(".");

}