2009-04-03 13 views
23

私は(私はそれらの多くより多くを持っている)には、次の2つのような、非常に似ていますが、単一の行を探し機能の配列を有する:は、パラメータの関数として二つのパラメータでデリゲートを渡す

private static int HowManyHoursInTheFirstYear(IList<T> samples) 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0; 

    while (count < samples.Count && 
      samples[count].Date.Year == firstDate.Year) 
    { 
     count++; 
    } 

    return count; 
} 


private static int HowManyDaysInTheFirstMonth(IList<T> samples) 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0; 

    while (count < samples.Count && 
      samples[count].Date.Month == firstDate.Month) // <--- only change! 
     count++; 
    } 

    return count; 
} 

0:

HowManyDaysInTheFirstPeriod(
    samples, 
    delegate(DateTime d1, DateTime d2) { return d1.Month == d2.Month; }); 

が、それによって次のようにデリゲートを宣言:私はいくつかのエレガントな方法でコードでこの繰り返しを削除するために、デリゲートを使用して考えていた、それは私のようなものを呼び出すことが許されているだろう

とHowManyDaysInTheFirstPeriodは、以下のようなものにwhould:

残念ながら
private static int HowManySamplesInFirstPeriod 
    IList<T> samples, 
    DateComparer comparer) 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0; 

    while (count < samples.Count && comparer()) 
    { 
     count++; 
    } 
} 

、コンパイラは、比較演算は2つのパラメータを必要と文句を言い。

私は比較的新しいC#であり、ここでロードブロックを打ちました。 これはどのように解決しますか?

+3

ここで、C#を初めて使っている人は、これは非常に分かりやすい代理人の使い方です。反復を見つけ、それを代理人に分解するためのあなたへの誇り。 –

答えて

14

あなたはほぼそこにいます! comparer delegateパラメータは他の関数と同じです:それでも呼び出すには適切な引数を渡す必要があります。あなたのケースでは、それがこの変更を意味するようになるだろう:

while (count < samples.Count && comparer(samples[count].Date, firstDate)) 
{ 
    count++; 
} 

(また、私は上記の書かれているようsamplesはおそらく、samples.Countでなければならないことに注意してください。)

4

問題の2つの日付を比較元に渡す必要があります。それはおそらくのような単純な突き出ています:

private static int HowManySamplesInFirstPeriod 
    IList<T> samples, 
    DateComparer comparer) 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0; 

    while (count < samples.Count 
      && comparer(samples[count].Date, firstDate)) 
    { 
     count++; 
    } 
} 

それとも、それらを他の方法ラウンド(すなわちfirstDate、その後samples[count].Date)を渡したいことがあります。

0

デリゲートと比較される日付を渡す必要があります。 So:

comparer(samples[count].Date, firstDate) 
6

あなたは少し単純にそれを行うことができます。単に関数に日時から比較すべきものは何でも抽出デリゲート提供:

private static int HowManySamplesInFirstPeriod<T> 
    IList<T> samples, 
    Func<DateTime, int> f // a function which takes a DateTime, and returns some number 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0; 

    while (count < samples && f(samples[count].Date) == f(firstDate)) 
    { 
     count++; 
    } 
} 

をし、その後のような呼び出すことができます。(dt) => dt.year構文はあなたに新しいかもしれ

HowManySamplesInFirstPeriod(samples, (dt) => dt.Year); // to get the year 
HowManySamplesInFirstPeriod(samples, (dt) => dt.Month); // to get the month 

が、それはですより一般的な型のオブジェクトdtをとり、dt.yearを返す匿名のデリゲートを書くよりきれいな方法です。 代わりに昔ながらのデリゲートを書くこともできますが、これは良い方法です。:)

我々は他のジェネリック型パラメータを追加することで、もう少し一般的なそれにもかかわらずよりも、それを行うことができます。いつものように

private static int HowManySamplesInFirstPeriod<T, U> 
    IList<T> samples, 
    Func<DateTime, U> f // Let's generalize it a bit, since the function may return something other than int (some of the DateTime members return doubles, as I recall) 

をしかし、LINQは、よりよいまだ選択肢を提供します。

private static int HowManySamplesInFirstPeriod<T> 
    IList<T> samples, 
    Func<DateTime, int> f) 
{ 
    var firstVal = f(samples.First().Date); 
    return samples.Count(dt => f(dt.Date) = firstVal) 
} 
1

私は、元の使用法に合うように、Jalfの答えを少し変更する必要があると思います:

電話番号:

HowManyDaysInTheFirstPeriod(samples, (d1, d2) = > { return d1.Month == d2.Month; }); 
HowManyDaysInTheFirstPeriod(samples, (d1, d2) = > { return d1.Year == d2.Year; }); 
関連する問題