2013-07-02 54 views
2

我明白,我正在尝试做的是一些破解,但它仍然很有趣。非例外情况下,数组越界

我处于很有可能数组可能没有我期望的项目数量的情况。

这里的概念:

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 

我应该如何处理这种情况在逻辑上? A try/catch块似乎矫枉过正。

+0

你如何处理它?你需要抛出异常,还是可以从中恢复?如果没有足够的字符串,对您的程序意味着什么? –

+0

'derp.Split('x')[1] ?? “。”表示如果'derp.Split('x')[1]'中没有任何内容会打印字符'“。”'“。 – Izzy

+0

你应该得到一个最难读的代码的奖励;)问题出现在'derp.Split('x')[1]'中。你不能检查[1]是否为空,因为它不存在。 –

回答

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.. 
... 
... 
... 
... 
0

如果这是不是特殊情况,如果可以,请勿使用异常。

在这个具体的例子

,你可以避免使用异常,并只使用简单的边界控制,如(只是一个例子):

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

您应该使用if声明:

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

在这个特定的例子中...遍历结果:

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

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

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]不说有关数组元素的内容,任何上述不妙,所以它可以说是并不明显,为什么默认的应该是"."

0

迭代通过Split

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

foreach (var s in splitOutput) 
    Writer(s); 
} 
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("."); 

} 
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) ?? "."); 
1

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

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

+0

您可以使用String定义返回的数组的最大长度.Split()',你也可以定义最小值? – Izzy

+0

我不这么认为,你只能尝试一些解决方法,比如创建一个你需要的大小的数组,并从string.Split()中创建的数组中复制值。 –