質問
次のような何かを返すメソッドがある場合
public DataTable ReturnSomething()
{
try
{
//logic here
return ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
}
}
これは、 catch {}
ブロックが何も返さないため、明らかにコンパイラエラーを生成します。
したがって、戻り値を持つメソッドがある場合、try-catchブロックを使用しません。これは悪い習慣です。エラーがある場合、エラー文字列をそのエラーに設定したいと思います。しかし、その後、戻り値も必要です。助言?
解決
次のような一時変数に戻り値を保存します。
public DataTable ReturnSomething()
{
DataTable returnValue = null;
try
{
//logic here
returnValue = ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
}
return returnValue;
}
他のヒント
catchブロックで例外を発生/スローし、呼び出し元のメソッドで処理する必要があります。
public void invokeFaultyCode()
{
try
{
DataTable dt = ReturnSomething();
}
catch(Exception e)
{
// Print the error message, cleanup, whatever
}
}
public DataTable ReturnSomething() throws Exception
{
try
{
//logic here
return ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
throw;
}
}
PS:構文エラーで申し訳ありませんが、C#で少し錆びています。
発信者をtry catchでラップする必要があります...呼び出されるルーチンで発生する例外は発信者にバブルされ、そこでキャッチできます。
個人的には、例外を処理する呼び出し側が必要なので、このルーチンでtry catchするのはやり過ぎだと思います。
私の例では、これは次のようにコーディングされます...
private void DoSomething() {
try {
DataTable dt = ReturnSomething();
}
catch (Exception ex) {
}
}
public DataTable ReturnSomething() {
DataTable dt = new DataTable();
// logic here
return dt;
}
ErrorString変数は、エラーコード変数のように見えます。推奨される方法は、エラーコードに物事を保存するのではなく、必要に応じて例外を使用してエラー情報を直接渡すことです。
例外を呼び出し側にキャッチさせる場合と同じように、ErrorStringで事実上同じことを行います。メソッド自体からエラーに応答する責任を取り除きます。これは良い目標です。ただし、エラー文字列を使用しても、例外を使用しても何も得られません。実際、この方法で情報を失います。発生する可能性のあるエラーの種類はいくつでもあり、多くはエラーに関連する特別な例外があり、障害に関するコンテキスト情報を保持する独自の特別なプロパティがあります。メッセージを文字列に格納するだけで、この情報が失われます。
したがって、目標が、呼び出し元から発生しているエラーのタイプを隠すことを明確にしない限り、例外を通過させることによってのみ得ることができます。
もう1つ考慮すべき点は、これが本当にエラーシナリオであるかどうかです。もしそうなら、呼び出し元のメソッドが戻り値をまったく気にすることはほとんどありません。その場合、例外をそのままにして何も返さないので、心配する必要はありません。それが実際にエラーシナリオではなく、呼び出し元が続行し、他のことを行う場合、それは呼び出し元が決めることですよね?エラー文字列とダミーのDataTableまたはnullを返すことで得られる利点はまだありません。コンテキストのすべての失敗情報を含む例外をスローします。
「例外ルートをスローしないでください」という方向に進む場合(必ずしも推奨しているわけではありません)、MSが使用するTryParseアプローチに従うことができます。
次のようなもの:
private string FillDataTable(out DataTable results)
{
try
{
results = new DataTable(); //something like this;
return String.Empty;
}
catch (Exception ex)
{
results = null;
return ex.Message;
}
}
アプリケーションによって異なります。 null
、空の DataTable
、または状況に適したものを返すことができます。
まだメッセージを設定できると仮定してから、nullまたは同等のc#を返します
public DataTable ReturnSomething(){
try {
//logic here
return ds.Tables[0];
} catch (Exception e) {
ErrorString=e.Message;
return null;
}
}
これについてはどうですか:
public DataTable ReturnSomething(out string errorString)
{
errorString = string.Empty;
DataTable dt = new DataTable();
try
{
//logic here
dt = ds.Tables[0];
}
catch (Exception e)
{
errorString = e.Message;
}
return dt;
}
あなたの例では例外を処理しているので(再度投げないように)、外部コードはすべてが正常であると想定しているため、有用なものを返す必要があります。
そこで例外をキャッチして問題なく処理する必要がある場合でも、それでもエラーの場合は、InnerExceptionとしてキャッチした例外など、別の例外をスローする必要があります。
コードはコールスタックの十分に高いレベルで実行されており、UIコードとブレンドされていると思います。これが本当に当てはまる場合、catchブロックで nullを返す
を実行できます。ただし、再利用可能なコードを記述している場合は、UI操作を含まないようにリファクタリングし、呼び出しスタックの上位レベルで例外を処理する必要があります。
次のサンプルコードのように実行できます。
public DataTable ReturnSomething(out string OutputDesc)
{
try
{
//logic here
OutputDesc = string.Format("Your Successful Message Here...");
return ds.Tables[0];
}
catch (Exception e)
{
OutputDesc =e.Message;
return null;
}
}