5

(私は似たようなスレッドを検索しましたが、このような問題に対処するものは見つかりませんでした。ここにそしてここに。)

私たちのアプリのパフォーマンスを評価していて、いくつかのIOException「リソースが見つかりません」を受け取っていることに気付いています。何回起こっているのか(私はユーザーのアプリの使い方に大きく依存しますが)正確にはわかりませんが、少なくとも1ダースかそこらです。

私は、一般的な例外は、ファイルI / O呼び出しがそうであるようにパフォーマンスが高いと思います。File.Exists()。試してロードする前にファイルが存在するかどうかをチェックすることは常に良い習慣であることを私は知っています。私の質問は、この特定のファイルが存在するかどうかを確認した場合、どの程度のパフォーマンスの向上が見られるかということです。 (繰り返しますが、「とにかくこれを実行する必要があります」は無視します。パフォーマンスについて理解しようとしているだけです)。

オプション1:

try
{
    return (ResourceDictionary) Application.LoadComponent(uri);
}
catch (Exception)
{
    //If it's not there, don't do anything
}

これは余分なIO呼び出しをしませんが、時々投げられて飲み込まれる例外を投げます。

オプション2

if(File.Exists(uri))
{
    return (ResourceDictionary) Application.LoadComponent(uri);
}


  • それが「常にベストプラクティス」であることをどのようにして知っていますか。 - Gabe
  • 選択肢2は競合状態を導入する。 - asawyer
  • オプション2は競合状態です。以前にそれを確認したとしても、IO操作は失敗する可能性があります。 - Mike Zboray
  • そうです、必ずしもそうとは限りませんが、一般的に言って、ファイルが存在するかどうかを常に確認する必要があります。いくつかの大学の課題は、チェックしないためのドッキングポイントでした;) - Devin
  • それはあなたが外因性の例外と呼ぶものです。blogs.msdn.com/b/ericlippert/archive/2008/09/10/… - asawyer

3 답변


6

一般に、ファイルがすべき存在する場合(つまり、それはあなたのアプリケーションのデプロイメントの一部です)、それから私は例外チェックを使用しますが、それ以外は何もしません。これは、この場合、例外が本当に例外的で予想外の状況であるためです。

ファイルがユーザーによって入力されたものである場合、存在を確認することは潜在的に意味があります。ただし、ファイルとしては、これでも例外処理が不要になるわけではありません。できたチェックしてから開いたり使用したりするまでの間に削除してください。そのように、あなたはまだ例外処理を必要としている - その場合あなたはよろしくまだ最初のオプションコードだけを使いたいのですが、たとえファイルが存在しなくても例外処理が常に振る舞いを提供するのに十分きれいであることを確認してください。


  • 仰るとおりです。残念ながら、これを実装した開発者は、特定の状況では存在しない可能性があることを認識していなかったと思います。ロードされているファイルはデプロイされますが、特定のアセンブリに対してのみデプロイされますが、このロジックは、そのファイルが存在しないアセンブリで呼び出される可能性がある基本クラスに存在します。 - Devin
  • とにかくFile.Existsは内部的に例外を投げるので、最終的な結果は同じです。 - rolls

1

私はあなたの2つのオプションの間に大きなパフォーマンスの違いがあるのを見ることができません。ほとんどの作業はファイルの場所を特定して読み取ることなので、どちらの場合もそうする必要があります。アプリケーションの実行中にユーザーがこのファイルを追加または削除することを想定していない場合は、便利なことがあります。だからあなたは何かをするかもしれません

private static Dictionary<Uri, ResourceDictionary> _uriToResources =
  new Dictionary<Uri, ResourceDictionary>();
public static ResourceDictionary GetResourceDictionary(Uri uri)
{
  ResourceDictionary resources;
  if (_uriToResources.TryGetValue(uri, out resources))
  {
    return resources;
  }

  try
  {
     resources = (ResourceDictionary)Application.LoadComponent(uri);
  }
  catch
  {
     // could prompt/alert the user here.
     resources = null; // or an appropriate default.
  }

  _uriToResources[uri] = resources;
  return resources;
}

これにより、存在しないリソースを繰り返しロードしようとするのを防ぐことができます。ここではnullオブジェクトを返しますが、フォールバックとしてデフォルトを使用する方が良いかもしれません。


1

File.Existsは内部的にも例外をスローします。そのため、パフォーマンスは非常によく似ています。

これは、File.Existsが呼び出すヘルパーメソッドを含むFile.csのコードです。

 [SecurityCritical]
    private static bool InternalExistsHelper(string path, bool checkHost)
    {
      try
      {
        if (path == null || path.Length == 0)
          return false;
        path = Path.GetFullPathInternal(path);
        if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1]))
          return false;
        FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false);
        return File.InternalExists(path);
      }
      catch (ArgumentException ex)
      {
      }
      catch (NotSupportedException ex)
      {
      }
      catch (SecurityException ex)
      {
      }
      catch (IOException ex)
      {
      }
      catch (UnauthorizedAccessException ex)
      {
      }
      return false;
    }

リンクされた質問


関連する質問

最近の質問