2013-07-02 55 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()中創建的數組中複製值。 –