C#泛型代码膨胀 - 我应该担心吗?

时间:2017-09-23 13:47:07

标签: c# generics

我想问一些关于泛型的事情。

我正在尝试保持代码简单,因此我将创建一个单独的类来处理游戏的存储游戏文件的加载/保存。由于游戏的每个部分都有不同的要求,我希望尽可能方便地访问:

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?它看起来并不好。

所以真正的问题是......我可以使用我在这里的下一个版本,还是因为使用泛型而我应该有这些问题?

2 个答案:

答案 0 :(得分:4)

reference types没有通用代码膨胀 - 代码被重用。但是,对于值类型,CLR将为每种类型生成单独的方法。看到 .NET Generics and Code Bloat

答案 1 :(得分:3)

using语句与错误处理无关。使用File.Open方法,您可以获得here找到的例外情况。通过将using语句包装在如下所示的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);

进行上述更改后,您可以通过单元测试更轻松地对方法进行测试,并且更加可靠,因为您在方法的肉和土豆之前进行了一些前置条件检查。如果您通过了空path会发生什么?如果您通过了null格式化程序会发生什么?等...

相关问题