5

私は 2 つの辞書を持っています。1 つはホストとして持っているファイル転送用で、もう 1 つはクライアントとして持っているファイル転送用です。

プログラムの領域の 1 つで実行しているコードは、これらの項目のいずれかを参照することを除いて、まったく同じです。このため、可能であればコードの重複を防止しようとしています。

public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
{
    // If the role is Sender then the variable is fileTransferSessionsAsHost, otherwise it is fileTransferSessionsAsClient.
    var fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost : fileTransferSessionsAsClient;


    foreach (var hostSession in fileTransferSessions)
    {
         Do Work in here.
    }
}

明らかに三項演算子は機能しませんが、私がしようとしていることを実行するコードを作成するにはどうすればよいでしょうか? ロールが送信者の場合、変数を への参照にしたいのですがfileTransferSessionsAsHost、それ以外の場合は にしたいと思いますfileTransferSessionsAsClient

私はこれについて鈍感な方法で行っていますか?コードを複製して、2 つの if ステートメントを作成する必要がありますか?

編集:

これは、より良い方法が見つからない場合、私が今しなければならないことです。見てみると、名前とディクショナリ項目の参照を除いて、コードはそれぞれ同じです。

        public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
    {
        if (role == FileTransferItem.FileTransferRole.Sender)
        {
            foreach (var hostSession in fileTransferSessionsAsHost)
            {
                var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == hostSession.Key.SessionId);
                if (fileTransferItem == null)
                {
                    activeFileTransfers.Add(new FileTransferItem(hostSession.Key.FileName,
                                                                 hostSession.Key.FileExtension,
                                                                 hostSession.Key.FileLength,
                                                                 FileTransferItem.FileTransferRole.Sender,
                                                                 hostSession.Key.SessionId));
                }
                else
                {
                    fileTransferItem.Update(hostSession.Value.TotalBytesSent,
                                            hostSession.Value.TransferSpeed,
                                            hostSession.Value.TotalBytesSent == hostSession.Key.FileLength);
                }
            }
        }
        else
        {
            foreach (var clientSession in fileTransferSessionsAsClient)
            {
                var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == clientSession.Key.SessionId);
                if (fileTransferItem == null)
                {
                    activeFileTransfers.Add(new FileTransferItem(clientSession.Key.FileName,
                                                                 clientSession.Key.FileExtension,
                                                                 clientSession.Key.FileLength,
                                                                 FileTransferItem.FileTransferRole.Sender,
                                                                 clientSession.Key.SessionId));
                }
                else
                {
                    fileTransferItem.Update(clientSession.Value.TotalBytesSent,
                                            clientSession.Value.TransferSpeed,
                                            clientSession.Value.TotalBytesSent == clientSession.Key.FileLength);
                }
            }
        }
    }
4

4 に答える 4

2

必要なものを得るには、両方のクラスが同じ基本クラスまたはインターフェイスから派生する必要があります。たとえば、 という共通インターフェースがある場合IFileTransferSessions、次のコードが機能するはずです。

IFileTransferSessions fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost : fileTransferSessionsAsClient;

varまたは、本当に構文を維持したい場合:

var fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost as IFileTransferSessions : fileTransferSessionsAsClient;

最初の 3 次結果のみをインターフェイスにキャストする必要があることに注意してください。または、両方を行うこともできます。

varキーワードは、Variantコンパイル時に型が何であるかを気にしない VB とは異なります。(これは C# に近いdynamicです) それが行うのは、次の使用法から型を派生させることだけです。2 つの異なるクラスを派生させるには、共通の基本クラスまたはインターフェイスを共有する必要があり、その場合でも、var適切に機能するためにその基本定義について知る必要があります。

于 2013-01-04T03:29:09.487 に答える
1

これを解決するには、いくつかの異なる方法があります。インターフェイスを使用するのが最も安全で合理的​​な方法です (または基本クラスを使用します)。それらは同じプロパティを実装しているため、両方ともそれらのプロパティを公開するインターフェイスを持ち、それらをインターフェイスにキャストできます。

インターフェイスを使用するようにクラス定義を変更できない (または変更しない) 場合は、リフレクションまたは動的も使用できます。これらはどちらも、インターフェイスを使用して発生するコンパイル時よりも悪い実行時エラーの影響を受けやすくなります。dynamic を使用すると、構文が少しきれいになり、リフレクションよりも簡単に記述できます。両方のアイテムを動的にキャストし、動的参照に保存するだけです。次に、必要なプロパティを呼び出すことができます。

dynamic fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? 
    (dynamic)fileTransferSessionsAsHost :
    (dynamic)fileTransferSessionsAsClient;

動的型付けに関する情報: http://msdn.microsoft.com/en-us/library/dd264736.aspx

于 2013-01-04T03:36:59.160 に答える
0

少なくともhostSessionとclientSessionの両方を同じ基本クラスまたはインターフェイスから派生させることができる場合は、コードの一部を除外することでコードを大幅に削減できます。

public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
{
    if (role == FileTransferItem.FileTransferRole.Sender)
    {
        foreach (var hostSession in fileTransferSessionsAsHost)
        {
              UpdateTransfers(hostSession);
        }
    }
    else
    {
        foreach (var clientSession in fileTransferSessionsAsClient)
        {
              UpdateTransfers(clientSession);
        }
    }
}

private void UpdateTransfers(SessionBaseType session)
{
            var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == session.Key.SessionId);
            if (fileTransferItem == null)
            {
                activeFileTransfers.Add(new FileTransferItem(session.Key.FileName,
                                                             session.Key.FileExtension,
                                                             session.Key.FileLength,
                                                             FileTransferItem.FileTransferRole.Sender,
                                                             session.Key.SessionId));
            }
            else
            {
                fileTransferItem.Update(session.Value.TotalBytesSent,
                                        session.Value.TransferSpeed,
                                        session.Value.TotalBytesSent == session.Key.FileLength);
            }
}

共通の祖先を持つようにセッションクラスを変更できない場合、他のアプローチは、必要なプロパティを公開するラッパークラスを作成することです。ただし、の代わりに上記のコードを使用する場合を除いて、基本的に上記のコードを使用できUpdateTransfers(clientSession);ます。UpdateTransfers(new SessionWrapper(clientSession));

于 2013-01-04T06:20:50.160 に答える
0

このコードを検討してください。

Dictionary<int, string> d1 = new Dictionary<int, string>();
Dictionary<int, string> d2 = new Dictionary<int, string>();

bool flag = true;

var d = flag ? d1 : d2;

d1との型がd2一致する (または一方から他方へのキャストがある) ため、機能します。これが鍵です。三項演算子によって返される値の型が異なる場合、演算子の戻り値の型を推測できず、それが問題になります。


実際には、オペランドの 1 つまたは両方を共通のインターフェイス (存在する場合) に明示的にキャストして、機能させることができます。

于 2013-01-04T03:09:08.850 に答える