2

私はいくつかのクラスを持っているとしましょう - 仮定の例:

public class InvalidResponseException<TReq, TResp> : Exception
{
    public TReq RequestData { get; protected set; }
    public TResp ResponseData { get; protected set; }

    public InvalidResponseException(string message, TReq requestData, TResp responseData)
        : this(message, null, requestData, responseData)
    {
    }

    public InvalidResponseException(string message, Exception innerException, TReq requestData, TResp responseData)
        : base(message, innerException)
    {
        RequestData = requestData;
        ResponseData = responseData;
    }
}

さて、クラスが定義されました...そしてコンパイル、問題ありません。

コード本体の別の場所で、この例外をスローして、1 つ以上の型の例外に匿名オブジェクトを渡したいとしましょう。これにより、コードベース内の呼び出しから予期しない応答を受け取る場所ならどこでも使用できるように、十分に汎用性が保たれるはずです。

var reqData = new { 
    Context = SomeDataContext,
    Username = SomeUserName,
    ParentID = 54,
    RequestValues = ListOfItemsToGet
}

var respData = results.ToList();

string exceptionMessage = string.Format("Invalid response data detected. Requested {0} items received {1}.", ListOfItemsToGet.Count(), results.Count());

throw new InvalidResponseException(exceptionMessage, reqData, respData);

ほとんどの匿名呼び出しでは型推論を使用できるため、メソッド呼び出しで型を定義する必要はありません...しかし、このコードはコンパイルされません。

マウスをreqDataの「var」の上に置くと、コンパイラーは、誰も手動で割り当てることができない奇妙な名前ではありますが、型が定義されていることを教えてくれます...理論的には、型はそれから推測できると思います。

私の最初の結論は、匿名型をジェネリックに渡すことはできないということでしたが、実際には何らかの方法で匿名オブジェクトをジェネリックに渡すことができます。

var BritishExpats = from p in People
                    where p.CountryOfBirth == "United Kingdom" && p.CountryOfResidents != p.CountryOfBirth
                    select new { FirstName = p.FirstName, LastName = p.LastName }

ここで、「BritishPeople」は IEnumerable<T> であり、T は 'a であると推測されます

...結果の匿名オブジェクトの IEnumerable を反復処理し、それらのパブリック プロパティを問題なく参照できます...

foreach (var ExPat in BritishExpats)
{
    Console.WriteLine("{0}, {1}", Expat.LastName, Expat.FirstName);
}

もちろん、"BritishExpats" がどのタイプなのかよくわからないので、ループで 'var' を使用する必要があります。

したがって、匿名オブジェクトによって推論された型を使用していくつかの型のクラスをインスタンス化できますが、他の型はインスタンス化できません...

...匿名オブジェクトによってインスタンス化、推論、および推論できないものについて、韻または理由はありますか?

4

2 に答える 2

2

ジェネリック、匿名型、および型推論をコンストラクターにまとめることはできません。コンパイラはそれを取得しません。次のようなヘルパー クラスを使用して回避策を作成できます。

public static class InvalidResponseExceptionHelper
{
    public static InvalidResponseException<TReq, TResp> Create<TReq, TResp>
        (string message, TReq requestData, TResp responseData)
    {
        return new InvalidResponseException<TReq, TResp>(message, 
            requestData, responseData);
    }
}

また、言及しませんでしたが、InvalidResponseException大幅に変更しない限り、クラスはコンパイルされません。ただし、あなたの質問の概念は通り抜けました。

于 2013-01-11T04:36:42.637 に答える
0

あなたの例は正しくありません。コンストラクターにジェネリック型を指定する必要はありません。それらはすでに知られています。

次の行は無効であり、コンパイルできません

public InvalidResponseException<TReq, TResp>(string message) // TReq,TResp are already known to constructor

以下のようなものが必要だと思います

public  class InvalidResponseException<TReq, TResp> : Exception
{
    public TReq RequestData { get; protected set; }
    public TResp ResponseData { get; protected set; }

    public InvalidResponseException (string message):
        this(message, default(TReq), default(TResp))    
    {
    }
    public InvalidResponseException (string message, TReq requestData, TResp responseData)  : base(message)
    {
        RequestData = requestData;
        ResponseData = responseData;
    }

}

次に、以下を試します(型推論を利用するため)

  throw new InvalidResponseException(exceptionMessage, "Exception Request", "Exception Response");
于 2013-01-11T04:38:36.127 に答える