2

我知道我正在尝试做的有点像 hack,但它仍然很有趣。

我处于一种情况,一个数组很可能没有我期望的那么多项目。

这是概念:

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块似乎过大了。

4

9 回答 9

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..
...
...
...
...
于 2013-07-02T10:09:16.817 回答
1

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

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

于 2013-07-02T10:16:26.727 回答
1

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

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

如果还有其他特定情况..那么这显然可能不符合您的要求。

于 2013-07-02T10:08:34.763 回答
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]没有说明该数组元素的内容,所以可以说为什么默认值应该是".".

于 2013-07-02T10:08:37.753 回答
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) ?? ".");
于 2013-07-02T10:11:41.410 回答
0

如果这不是异常情况,请尽可能不要使用异常。

在这种具体情况下,您可以避免使用异常并仅使用简单的边界控制,例如(只是一个示例):

var splitted = derp.Split('x');
if(splitted.Length > 1) {
   Writer(derp.Split('x')[0] ?? ".");
   Writer(derp.Split('x')[1] ?? ".");
}
于 2013-07-02T10:07:21.660 回答
0

您应该使用以下if语句:

var result = derp.Split('x');
if (result.Length > 0)
    Writer(result[0]);
else
    //...
于 2013-07-02T10:08:27.933 回答
0

遍历返回的数组Split

var splitOutput = derp.Split('x');

foreach (var s in splitOutput)
     Writer(s);
}
于 2013-07-02T10:08:48.117 回答
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(".");

}
于 2013-07-02T10:10:40.807 回答