我有一个方法,通常从用户提供的文件路径和对象类型反序列化存储的对象。该方法工作正常,但用户提供无效文件路径时除外。我希望我的方法在这种情况下返回null,但是当我尝试返回null时,我得到一个编译错误。我试图使用可空类型,但得到编译错误。相反,我对一个对象进行类型转换并返回该对象,但它会导致运行时错误。我想知道是否有人知道允许返回null的正确方法。代码如下:
public static T RestoreObj<T>(string datafile)
{
try
{
var fs = File.OpenRead(datafile);
var bf = new BinaryFormatter();
var obj = (T) bf.Deserialize(fs);
fs.Close();
return obj;
}
catch (Exception e)
{
MessageBox.Show("Could not load. Accepts valid *.dom files only. " + e);
// TODO: how to do this? this will throw a runtime error, and if null returned, a compilation error
var o = new object();
return (T) o;
}
}
考虑到Eric Lippert的质量评论之后,我修改了方法,看起来就像你在下面看到的那样。使用'using'的优点是它会自动生成一个try..finally块,它将调用dispose方法(FileStream实现IDisposable,如果不是它们将是一个编译错误)。另一件好事是抛出的异常与实际发生的事情有关,而不是我上面所做的。
public static T RestoreObj<T>(string datafile)
{
using (var fs = File.OpenRead(datafile))
{
var bf = new BinaryFormatter();
var obj = (T)bf.Deserialize(fs);
return obj;
}
}
答案 0 :(得分:20)
如果您只打算使用类,请添加where T : class
约束:
public static T RestoreObj<T>(string datafile) where T : class
如果您希望反序列化结构,那么只需返回default(T)
。对于引用类型,它将是null
,对于结构,它将是默认值(通常为0)。正如@JMH指出的那样,default(Nullable<T>)
是一个null
- 包含可空。
答案 1 :(得分:11)
我会通过不首先编写代码来解决问题。
一种方法应该做一件事,做得好;您正在使用错误报告代码混合反序列化代码。
不要那样做。更好的方法是让反序列化方法抛出异常,并编写不同的代码来处理异常并向用户报告错误。
更一般地说,拥有一个吃异常然后返回虚假数据的方法是危险的。这只是在不知情的调用你的方法的代码期望得到好的数据时,就会产生问题。
虽然我们讨论的是代码质量问题,但您应该使用“using”块来确保在发生异常时关闭文件句柄。不要明确地执行fs.Close()
- 而是执行using(var fs = ... )
并让编译器生成关闭文件的处理。
答案 2 :(得分:4)
您可以使用default(T)
代替null
null
作为参考类型和值类型的默认值。
答案 3 :(得分:2)
并非所有类型都可以设置为null
。
您必须约束T
:
public static T RestoreObj<T>(string datafile) where T : class
你的另一个选择(如果你没有严格使用类)是返回default(T)
而不是null。
答案 4 :(得分:1)
将约束放在T
上:
public static T RestoreObj<T>(string datafile) where T : class
//^^^^^^^^^^^^^^
这意味着您可以使用T
调用此方法,null
是一种可以T
的引用类型。当Nullable<V>
是值类型时,您无法调用此方法,但是当T为class R {} //Reference type!
struct V {} //Value type!
Xyz.RestoreObj<R>("abc"); //ok
Xyz.RestoreObj<V>("abc"); //compilation error
Xyz.RestoreObj<Nullable<V>>("abc"); //ok
时调用它:
{{1}}
答案 5 :(得分:1)
如果您声明这样的方法,则应该能够返回null
:
public static T RestoreObj<T>(string datafile) : where T class
T
也可以是一个结构,不能是null
。如果您将T
限制为类,则必须是引用类型,并且您可以返回null
。
答案 6 :(得分:0)
您可以使用以下内容检查文件是否存在,并返回该类型的默认值。
if (!File.Exists(FilePath))
return default(T);
通过使用此功能,您将获得该类型的默认值。例如,如果给它一个'int'类型,它将返回0而不是null。