2

そのため、C# はオプションのパラメーターをサポートしています。

void MethodName(string param = "optional!") { }

そして動的メソッドのパラメータ:

void MethodName(dynamic param) { }

残念ながら、これらを一緒に使用することはできません (オプションの param 値は定数でなければなりません):

void MethodName(dynamic param = new { p1 = "", p2 = 0M }) { }

私は過去に次のようなものを使用しました:

void GenericAnonHandler<T>(IEnumerable<T> param)
{
    foreach(T item in param)
    {
        var typedItem = Cast(item, new { p1 = "", p2 = 0M });
        var p2 = typedItem.p2; // Hark, IntelliSense!
    }
}    
static T Cast<T>(object obj, T type)
{
    return (T)obj;
}
void CallingMethod()
{
    var list1 = new List<ThisType>() { ... };
    var list2 = new List<ThatType>() { ... };

    var anon1 = list1
        .Select(x => 
            new { p1 = x.sPropName, p2 = x.dPropName });

    var anon2 = list2
        .Select(x => 
            new { p1 = x.sPropName2, p2 = x.dPropName2 });

     var both = anon1.Concat(anon2);

     GenericAnonHandler(both);
}

しかし、それは多くの余分な作業と型固有のコーディングであり、動的型がどうあるべきかを知っている限り、新しいクラスまたは単に動的を使用する方が簡単になります..しかし、動的はIntelliSenseを提供しません(そして合理的にそれで)。

インターフェイスを使用したいのですが、ソースの種類 (この例では ThisType、ThatType) のプロパティ名が異なり、それら (サードパーティのアセンブリ) を制御できないため、使用できません。

ただし、それらは部分クラスであるため、統一されたプロパティ名と異なるプロパティ名を持つ匿名型のシグネチャを使用してインターフェイスを作成し、部分的にインターフェイスを実装し、「その他」から欠落している値のダミー プロパティを作成できます。タイプに応じて、それぞれのプロパティから値を取得します。

..しかし、それも大変な作業です..特に、3 つの新しいアイテム (インターフェイス、2 つのパーシャル) を作成するためにあらゆる努力をしている場合はなおさらです。anon 型を実際のクラスとして作成し、前の 2 つの型から変換する方が簡単です。

私が望んでいることを達成するための巧妙な方法があるかどうかを尋ねるだけです。インテリセンスを機能させるオプションの動的パラメータ?

私はこれがばかげた質問であることを知っています..そして基本的には、実際にクラスを定義せずにクラスを定義するにはどうすればよいでしょうか.. Cast(T,Type) ルート以外のトリックを備えたウィザードがそこにあるかどうか疑問に思っています:)

4

2 に答える 2

4

ここでの答えは次のとおりです。これをしないでください。

短い定義で十分です。struct StrDec { public string p1; public decimal p2; }

これらの小さな定義を自由にたくさん使用してください。できれば、それらが表すものを実際に文書化した名前を付けてください。コンパイル時のチェック、インテリセンスが得られ、これはドキュメントの形式であるため、コードが読みやすくなります。代わりに を使用することもTupleできますが、コードが読みにくくなることがわかりました。それにもかかわらず、タプルはダイナミクス + 匿名タイプのハックよりも優れています。

良い出発点は...

  • 使用しないdynamic: これは最後の手段の機能です。
  • オプションの引数を使用しないでください。これも最後の手段です。

dynamic型システムを弱体化させ、本質的に、静的に型付けされた言語の悪い部分 (冗長) を取得し、良い部分 (高速、信頼性、自己文書化、インテリセンス) を取得することを意味します。価値があることはめったにありません。

オプションの引数は、1970 年代以来の構造化プログラミング 101 であるカプセル化可能性を壊すため、悪いものです。オプションの引数をラップすると、引数の指定が繰​​り返され、デフォルト値が繰り返されます。さらに、呼び出し先ではなく呼び出し元によって解決されるという事実に関する小さな技術的な制限があります。これは、かなり珍しい方法で dll を展開しない限り、問題になることはありません (この制限は、.NET 自体などの大規模なライブラリの場合に重要です)。 )。代わりに、(もう一度)小さくて使い捨てのstructs.

于 2013-02-21T22:37:45.990 に答える
0

動的でオプションの部分を捨てると思いますが、ここでは本当に必要ないようです。新しい型 (必要に応じてクラスまたは構造体) を作成します。

public class ThirdType
{
    public string P1 { get; set; }
    public decimal P2 { get; set ; }

    // you may want to add constructors
}

次に、いくつかのマッパー メソッドを作成します (拡張メソッドで問題ありません)。

public static class MapperExtensions 
{
    public static ThirdType ToThirdType(this ThisType obj)
    {
        return new ThirdType() { P1 = obj.sPropName, P2 = obj.dPropName };
    }

    public static ThirdType ToThirdType(this ThatType obj)
    {
        return new ThirdType() { P1 = obj.sPropName2, P2 = obj.dPropName2 };
    }
}

メソッドを呼び出すたびに、

void MethodName(ThirdType param)
{
    // A.) do this...
    if (param == null)
        param = new ThirdType() { P1 = "", P2 = 0M };

}

// ... or B.) create an overload (preferable to me)
void MethodName()
{
   MethodName(new ThirdType() { P1 = "", P2 = 0M });
}

拡張メソッドを使用するだけです。私が思うに、この方法でコードはより明確になります。

private void ExecuteForBoth(ThisType obj1, ThatType obj2) // dummy method, just for illustration
{
    MethodName(obj1.ToThirdType());
    MethodName(obj2.ToThirdType());
}

これはインテリセンスなしで書きました。タイプミスはごめんなさい。

于 2013-02-21T23:04:47.857 に答える