4

保存された質問 - 下部の編集を参照してください
。基本的に、基本的な循環的複雑さを隠すことで読みやすさを提供するために、小さな機能ライブラリに取り組んでいます。プロバイダーが呼び出されSelect<T>( と呼ばれるヘルパー ファクトリSelectを使用)、使用法は次のようになります。

public Guid? GetPropertyId(...)
{
    return Select
        .Either(TryToGetTheId(...))
        .Or(TrySomethingElseToGetTheId(...))
        .Or(IGuessWeCanTryThisTooIfWeReallyHaveTo(...))
        //etc.
        ;
}

ライブラリが短絡などを処理します。 からSelect<T>への暗黙的な変換も追加したTので、次のように記述できます。

public Guid GetPropertyId(...)
{
    ServiceResult result = Select
        .Either(TryToGetTheId(...))
        .Or(TrySomethingElseToGetTheId(...));

    return result.Id;
}

私が本当にできるようにしたいのは、割り当てなしの T への暗黙的な変換です。

public Guid GetPropertyId(...)
{
    return 
        //This is the part that I want to be implicitly cast to a ServiceResult
        Select
        .Either(TryToGetTheId(...))
        .Or(TrySomethingElseToGetTheId(...))
        //Then I want to access this property on the result of the cast
        .Id;
}

ただし、指定された構文は機能しません。変数に割り当てるか、明示的にキャストする必要があります。暗黙のキャストをインラインで取得する方法はありますか?

編集

私がやりたいことはこれです:

class Foo { 
    public int Fuh { get; set; } 
}

class Bar {
    private Foo _foo;
    public static implicit operator Foo (Bar bar)
    {
        return bar._foo;
    }
}

//What I have to do
Foo bar = GetABar();
DoSomethingWith(bar.Fuh);

//What I want to do
DoSomethingWith(GetABar().Fuh);
4

7 に答える 7

5

私の質問は: メンバー アクセス (「ドット」) 演算子を使用する場合、Bar のメンバーと Bar が暗黙的に変換可能な型の両方を検索するようにコンパイラに指示する方法はありますか?

はい、それには 2 つの方法があります。

1つ目は「継承」と呼ばれるものです。次のようにします。

class Bar : Blah { ... }
...
Bar bar = new Bar();
bar.Whatever();  // member access will look up members of both Bar and Blah.
Blah blah = bar; // bar is implicitly convertible to Blah.

これはコンパイラに「Bar のメンバーを検索するときは、Blah のメンバーも検索する」ことを伝えます。また、Bar のインスタンスが Blah 型に暗黙的に変換可能であることもコンパイラに伝えます。

Blah は、クラスまたはインターフェイス型のいずれかです。

2 つ目は、「型パラメーターに対するクラスおよびインターフェイスの制約」と呼ばれます。次のようにコンパイラにヒントを与えます。

void M<T>(T t) where T : Blah
{
    t.Whatever(); // member access looks up members of Blah on t
    Blah blah = t; // t is implicitly convertible to Blah

現在、t は Blah に暗黙的に変換可能であり、t のメンバー アクセスには、Blah で宣言されたメンバーが含まれます。

繰り返しますが、Blah はインターフェースまたはクラス型にすることができます。

C# には、追加されたメンバーが Blah 型で宣言されるように Bar 型のメンバー ルックアップに影響を与える他の方法はありません。ここで、Bar は暗黙的に Blah に変換可能です。

于 2010-09-14T16:02:36.527 に答える
5

Valueここで暗黙的なキャストが機能しないことは事実ですが、プロパティを に追加することで、明示的なキャストよりもうまくいく可能性がありますSelect<T>。次に、あなたの式は になりますがSelect.[operations].Value.Id、それでもかなりうまく読み取れます。

于 2010-09-13T19:41:22.157 に答える
2

それは不可能だと思います。キャストを発生させるには、何らかのオペレーターが関与する必要があります。コンパイラ/ランタイムは、タイプ T にしたいことを単に「知る」ことができません。何らかの方法でそうするように指示する必要があります。

于 2010-09-13T19:15:22.927 に答える
1

私はあなたの問題を見ていると思います。ではなく をOr返すため、オブジェクトからプロパティを取得することを期待していることをコンパイラが知る方法はありません。どうして?プロパティがないことを確認し、潜在的な暗黙の変換を探して、そのうちの 1 つに というプロパティがあるかどうかを確認する必要がありますか?SelectServiceResultIdServiceResultSelect.IdId

以下にいくつかの選択肢を示します。

public Guid GetPropertyId(...) 
{ 
    return  ((ServiceResult)
        Select 
        .Either(TryToGetTheId(...)) 
        .Or(TrySomethingElseToGetTheId(...)))
        .Id; 
} 

また

class Select
{
    public ServiceResult AsServiceResult()
    {
        return (ServiceResult)this;
    }
}

public Guid GetPropertyId(...) 
{ 
    return  
        Select 
        .Either(TryToGetTheId(...)) 
        .Or(TrySomethingElseToGetTheId(...)) 
        .AsServiceResult()
        .Id; 
} 

また

class Select
{
    public Guid Id { get { return ((ServiceResult)this).Id; } }
}

public Guid GetPropertyId(...) 
{ 
    return  
        Select 
        .Either(TryToGetTheId(...)) 
        .Or(TrySomethingElseToGetTheId(...)) 
        .Id; 
}
于 2010-09-13T20:33:29.890 に答える
1

guid への変換をインラインで行いたい場合は、拡張メソッドを実行できます

public static Guid ToGuid(this string id)
{
    return new Guid(id);
}

public Guid GetPropertyId(...)
{
    return Select
        .Either(TryToGetTheId(...))
        .Or(TrySomethingElseToGetTheId(...))
        .Id
        .ToGuid();
}

私はそれが本当に何かを追加するとは思わないが、私の視点では読む方が良い.

于 2010-09-13T19:25:17.353 に答える
0

試しましたか

public Guid GetPropertyId(...)
{
    return new Guid(Select
        .Either(TryToGetTheId(...))
        .Or(TrySomethingElseToGetTheId(...))
        .Id);
}
于 2010-09-13T19:12:30.130 に答える
0

特定のタイプのみを扱う場合は、ラッパー メソッドまたはプロパティを追加できます。myThing に「self.internalThing.Bar」を返す「Bar」型のメソッドがある場合、myThing を返す式が実際にはそのラップされた型の式を返しているという錯覚を維持できます。ただし、一般的なケースでそれを行う方法はありません。将来の C# および VB バージョンでは、クラス内の 1 つのプロパティを「ラップ」できるようにすることが役立つかもしれませんが、既存の言語でそれを行う方法はわかりません。

于 2010-09-13T19:47:59.243 に答える