c#4.0-如何在c#中进行异常处理
本文关键字:异常处理 c#4 | 更新日期: 2023-09-27 17:58:10
我有一个小控制台应用程序,它将在ExcelDataReader的帮助下读取excel数据。控制台应用程序的代码:
class Program
{
static void Main(string[] args)
{
SomeData data = new SomeData(@"C:'SC.xlsx", "somedata_2014");
IEnumerable<SomeType> someTypes = someData.GetData();
Console.ReadLine();
}
}
请不要担心变量的命名;这是为一家公司准备的,我不想使用任何与公司相关的东西。下一个是SomeData类:
public class SomeData
{
private string path;
private string worksheetName;
public SomeData(string path, string worksheetName)
{
this.path = path;
this.worksheetName = worksheetName;
}
public IEnumerable<SomeType> GetData(bool isFirstRowAsColumnNames = true)
{
var excelData = new ExcelData(path);
try
{
var ad = excelData.GetData(worksheetName, isFirstRowAsColumnNames);
return ad.Select(dataRow => new SomeType()
{
Gemeente = dataRow["LivingPlace"].ToString(),
Geslacht = dataRow["Outdoors"].ToString(),
Woonplaats = dataRow["WellHellYesOrNo"].ToString()
}).ToList();
}
catch (FileNotFoundException ex)
{
throw;
}
catch (ArgumentException ex)
{
throw;
}
}
}
最后,ExcelData类比SomeData类低一个级别:
public class ExcelData
{
private string path;
public ExcelData(string path)
{
this.path = path;
}
private IExcelDataReader GetExcelDataReader()
{
try
{
using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read))
{
IExcelDataReader dataReader = null;
if (path.EndsWith(".xls"))
{
dataReader = ExcelReaderFactory.CreateBinaryReader(fileStream);
}
if (path.EndsWith(".xlsx"))
{
dataReader = ExcelReaderFactory.CreateOpenXmlReader(fileStream);
}
return dataReader;
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
throw;
}
}
public IEnumerable<DataRow> GetData(string sheet, bool isFirstRowAsColumnNames = true)
{
var reader = GetExcelDataReader();
reader.IsFirstRowAsColumnNames = isFirstRowAsColumnNames;
var workSheet = reader.AsDataSet().Tables[sheet];
var rows = from DataRow row in workSheet.Rows select row;
return rows;
}
}
我想做的是,当打开excel文件时出现问题时,我希望它抛出一个异常,并且我希望它出现气泡,这样我就可以在最高级别上写出它。
SomeData类的GetData方法也是如此;当我想读取某一列的数据,但出现问题时,我希望它抛出一个冒泡的异常,这样我就可以再次在顶层写出它。
我只是在寻找最好的方法。
默认情况下出现异常"bubble";不做任何事情就重新抛出异常是没有意义的,这只是浪费了代码和CPU。事实上,这几乎就是异常的全部操作方式-无论发生什么,无论发生在哪里,都会由第一个准备好处理它的人来处理。所以你只需要在你真正准备好处理的时候使用try { ... } catch (WhateverException ex) { ... }
。
任何根本没有处理的异常都会杀死你的应用程序(尽管要注意,像Winforms这样的某些框架会给你一个选择,例如尝试并继续——不过,总的来说,你应该自己处理所有这些,这只是最后的安全网)。
在"较高"级别捕获异常的最佳方法是在"较低"级别根本不捕获它们。它们会自动冒出来,你可以在任何你认为合适的时候抓住/处理它们。
没有理由使用这样的代码,因为您所做的唯一事情就是重新抛出异常。
catch (FileNotFoundException ex)
{
throw;
}
catch (ArgumentException ex)
{
throw;
}
像这样的代码很好,因为你在重新抛出异常之前要对它进行处理。例如,你可能会在重新抛出它之前记录一个异常,这样调用方法也可以捕捉并处理它(比如向用户显示错误)。
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
throw;
}
如果您可以在较低级别处理和修复问题,请在那里捕获异常并修复问题。如果你想让所有的异常都冒泡到顶部,在那里你可以提醒用户,然后删除所有的try/catch块,只在Main
:中捕获
try
{
SomeData data = new SomeData(@"C:'SC.xlsx", "somedata_2014");
IEnumerable<SomeType> someTypes = someData.GetData();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
只是不要在每个方法中都捕获异常-只有当你能对它做一些事情时,你才应该捕获异常(处理它(即不重新抛出它),添加一些重要的上下文信息,或者如果它对日志记录很重要)
所以你想的方法是好的,要么让它弹出到gui,要么,如果你能处理/添加信息,你也可以在数据类中捕捉它,但我不会在我使用的每个类中捕捉到它
当然,这个决定还取决于你的哪些部件被其他应用程序/组件重用。
还有一件事是异常链接:低级别异常(例如"除以零")被重新评估为新的异常,如"数据异常"。。取决于您的应用程序模型
我想您要做的是将错误气泡上升到顶层,这样您就可以看到它在多个级别上被抛出的位置。我说得对吗?无论如何,您不需要catch/sthrow语句,而是定义一个方法像一样可丢弃
public IEnumerable<SomeType> GetData(bool isFirstRowAsColumnNames = true) throws Exception
在这种情况下,如果GetData中发生错误,它将向上冒泡您还可以定义应该抛出什么类型的表达式,或者定义可以抛出的多个异常