2017-09-23 90 views
2

我想問一些關於泛型的內容。C#泛型代碼膨脹 - 我應該擔心嗎?

我想保持代碼簡單,因此我將製作一個類來處理加載/保存遊戲的savegame文件。隨着遊戲的每個部分都有不同的要求,我想擁有這個方便地:

public void Load<T>(string path, out T obj) 
{ 
    BinaryFormatter bf = new BinaryFormatter(); 
    using (FileStream file = File.Open(Application.persistentDataPath + path, FileMode.Open)) 
    { 
     obj = (T)bf.Deserialize(file); 
    } 
} 

現在我可以用一個簡單的

TurnData x; s.Load("test.txt", out x); 

替代稱這將是使Load函數返回對象,然後將其轉換爲TurnData類型。

TurnData x = (TurnData)s.Load("test.txt"); 

我對C#不太瞭解。我假設using(...) { ... }裏面的代碼沒有得到執行,如果打開文件時出現錯誤,例如?如果有人能證實這會很好。我看到的示例代碼沒有任何錯誤處理,這對我來說似乎很奇怪,所以我添加了使用?

因此,在此次要版本中,函數返回對象而不是使用out參數,則需要更復雜的錯誤檢查代碼並可能返回null?這看起來不太好。

所以真正的問題是......我可以使用我在這裏的下一個版本,還是有擔心,我應該由於使用泛型?

+1

'使用'塊只是try {}的簡化版本finally {//將處理一次性對象}' – SeM

+0

基本上它調用對象的Dispose()方法,即使塊內的代碼拋出一個異常。 – SeM

+0

我不明白你爲什麼使用泛型*編寫代碼*。爲什麼'Foo foo;加載(path,out foo);'以任何方式比'Foo foo =(Foo)Load(path)更好;'?後者似乎對我來說更加清晰,而且更簡單。你這樣做的建議有很大的價值,你應該考慮這樣做。你將不得不以任何方式編寫錯誤處理。 –

回答

3

using聲明與錯誤處理無關。使用File.Open方法,您會發現例外情況,您會發現here。你能避免突然通過包裹你使用的語句在try/cath結構如下圖所示,從任何這樣的異常中斷程序的:

public T Load<T>(string path) 
{ 
    T obj = default(T); 
    var bf = new BinaryFormatter(); 
    try 
    { 
     using (var file = File.Open(Application.persistentDataPath + path, FileMode.Open)) 
     { 
      obj = (T)bf.Deserialize(file); 
     } 
    } 
    catch(Exception exception) 
    { 
     // Log the exception 
    } 
    return obj; 

} 

基本上你試圖打開路徑指定的文件。如果失敗,您只需記錄故障並從功能中返回null

關於using聲明,它提供

一個方便的語法,確保正確使用IDisposable的 對象。

,你可以作爲一個側面說明閱讀更徹底here

關於你的方法的簽名我講幾點意見。考慮下面的方法主體,並找出與上面的不同之處。

public T Load<T>(string path, IFormatter formatter) 
{ 
    if(path ==null) throw new ArgumentNullException(nameof(path)); 
    if(formatter == null) throw new ArgumentNullException(nameof(formatter)); 

    T obj = default(T); 
    try 
    { 
     using (var file = File.Open(path, FileMode.Open)) 
     { 
      obj = (T)formatter.Deserialize(file); 
     } 
    } 
    catch(Exception exception) 
    { 
     // Log the exception 
    } 
    return obj; 
} 

var path = Path.Combine(Application.persistentDataPath, "test.txt"); 
var binaryFormatter = new BinaryFormatter(); 
var x = s.Load(path, binaryFormatter); 

作出上述改變你讓你的方法更容易通過單元測試,因爲你做了一些前提條件的方法的香餑餑之前檢查測試,更可靠。如果您通過了null path,會發生什麼情況?如果你通過了一個空格式化程序,會發生什麼?等等...

+1

此代碼無法編譯:CS0403無法將null轉換爲類型參數'T',因爲它可能是非空值類型。考慮使用'default(T)'。 –

+1

@PavelTupitsyn你是非常該死的正確!我只是糾正它。謝謝 – Christos

+0

@StuartLC非常感謝您的評論。 Pavel也指出了這一點:) – Christos

4

reference types沒有泛型代碼膨脹 - 代碼被重用。不過,對於值類型,CLR將爲每種類型生成一個單獨的方法。見 .NET Generics and Code Bloat

+0

我知道我讀過這個,這就是爲什麼我明確指出單聲道是,在這不一定適用 –