3

virtual「GetBaseAddresses()」というメソッドを持つ基本クラスを作成しています。リターンタイプとしてありIEnumerable<Uri>ます。基本クラスをyield列挙しても結果は得られませんが、派生クラスには、メソッドをオーバーライドして、必要な数のアイテムを返すオプションがあります。

基本的な方法は次のとおりです。

public virtual IEnumerable<Uri> GetBaseAddresses() { }

問題は、それがコンパイルされないことです。コンパイラが満足するためには、値を返す必要があります。だから、私は空の結果を出したいので、私はただ戻るでしょうnull

public virtual IEnumerable<Uri> GetBaseAddresses() { return null; }

問題は、誰かがforeach基本クラスのインスタンスでを実行すると、「オブジェクト参照が設定されていません...」という実行時エラーでクラッシュすることです。

それで、yield returnキーワードがC#コンパイラで魔法をかけることを思い出してください...私はこのコンパイラハックを思いつきました(ちなみにそれは機能します)。

public virtual IEnumerable<Uri> GetBaseAddresses()
{
    if (false) { yield return new Uri(""); }
}

不思議なことに、「if(false){...}」コードが完全にコンパイルされても、コンパイラは「値を返さなければならない」要件を満たしていることに満足しており、私が望むことを正確に実行します。つまり、列挙しても安全な空の結果セット。

私の質問は-コンパイラのトリックなしでこれを行う方法はありますか?

4

4 に答える 4

10

空の配列を使用するか、次のようにします。

yield break; //end enumeration

コメントからsvickのアイデアを引き出す:

return Enumerable.Empty<Uri>();

これはEnumerable.Empty、空の列挙型のキャッシュされた事前に割り当てられたインスタンスを常に返すため、より高速です。

于 2012-06-13T22:05:52.123 に答える
9

基本メソッドで空の列挙型を返すだけです。

    public virtual IEnumerable<Uri> GetBaseAddresses()
    {
        return Enumerable.Empty<Uri>();
    }

または、バージョン 3.5 より前の .NET フレームワークをターゲットにしている場合は、空のリストを返します。

于 2012-06-13T22:07:39.373 に答える
5

組み込み配列は IEnumerable をサポートしているため、次を使用できます。

public virtual IEnumerable<Uri> GetBaseAddresses() 
{     
      return new Uri[0];
}
于 2012-06-13T22:04:14.117 に答える
0

空のメソッドが機能しない理由はyield、メソッドでキーワードを使用しない場合、イテレータではなく通常のメソッドを作成する必要があるとコンパイラが想定しているためです。それがあなたのif (false)ハックが機能する理由でもあります。

空のコレクションを返すメソッドを適切に記述するには、通常の方法で空のコレクションを返すことができます。

public virtual IEnumerable<Uri> GetBaseAddresses()
{
    return Enumerable.Empty<Uri>();
}

または、次を使用できますyield break

public virtual IEnumerable<Uri> GetBaseAddresses()
{
    yield break;
}
于 2012-06-13T23:17:17.077 に答える