2

I'm trying to call a "Sort" method that expects a parameter of type IComparer<object>, using the code:

collection.Sort((IComparer<object>)Comparer<DateTime>.Default)

It builds but at run time I get an InvalidCastException with the message:

Unable to cast object of type
'System.Collections.Generic.GenericComparer`1[System.DateTime]'
to type 'System.Collections.Generic.IComparer`1[System.Object]'.

Now what?


If you don't need to write to the command, then just change the 'w' to 'r':

strpath = "sudo svnadmin create /svn/repos/" + short_name
output = os.popen (strpath, 'r')

for line in output.readlines():
    # do stuff

Alternatively if you don't want to process line-by-line:

strpath = "sudo svnadmin create /svn/repos/" + short_name
output = os.popen (strpath, 'r')

outtext = output.read()

However, I'd echo Greg's suggestion of looking at the subprocess module instead.

4

5 に答える 5

7

デフォルトの比較だけが必要な場合、これは機能します。

collection.Sort(Comparer<object>.Default)

Comparer.Defaultは、オブジェクト固有の比較セマンティクス(つまり、IComparable.CompareTo)を使用します。

于 2009-09-03T22:59:34.233 に答える
4

残念ながら、適切なタイプの比較子が必要です。

IComparer<object>DateTime 比較子をラップしただけのカスタム クラスを作成できますが、キャストを介して直接これを行う方法はありません。

コレクションに常に DateTime オブジェクトが含まれている場合は、次のようにするだけです。

ICollection<DateTime> collection = ...;
collection.Sort(Comparer<DateTime>.Default); // or just collection.Sort()

コメントを読んだ後に編集します。

ICollection を直接操作している場合は、LINQ オプションを使用して次のことを行うことができます。

collection.Cast<DateTime>().OrderBy( date => date );

を実装するものIList<T>( などList<DateTime>) を使用している場合は、リスト自体で Sort() を呼び出すだけです。


非標準クラスを使用しているため、独自の比較子を作成する必要があります。

class Comparer : IComparer<object> {
    int Compare(object a, object b) {
         return DateTime.Compare((DateTime)a, (DateTime)b);
    }
}

その後、次のように呼び出すことができます。

collection.Sort(new Comparer() );
于 2009-09-03T19:02:40.637 に答える
3

次のような拡張関数を定義できます。

public static class ComparerConversion
    {
        private class ComparerWrapper<T> : IComparer<object>
        {
            private readonly IComparer<T> comparer;

            public ComparerWrapper(IComparer<T> comparer)
            {
                this.comparer = comparer;
            }

            public int Compare(object x, object y)
            {
                return this.comparer.Compare((T)x, (T)y);
            }
        }

        public static IComparer<object> ToObjectComparer<T>(this IComparer<T> comparer)
        {
            return new ComparerWrapper<T>(comparer);
        }
    }

次のように使用します。

List<object> collection = new List<object> { DateTime.Now.AddDays(1), DateTime.Now };
collection.Sort(Comparer<DateTime>.Default.ToObjectComparer());
于 2009-09-03T21:17:51.327 に答える
3

コレクション オブジェクトの型を (つまり、ArrayListから にList<object>) 変更できる場合は、非ジェネリックIComparerインターフェイス (Comparer<DateTime>.Default実装) を使用できます。

コレクション オブジェクトの型を変更できない場合は、運が悪いです。IComparer<object>(次のように、を実装するオブジェクトをいつでも実装できます。

 public class DateTimeComparer : IComparer<object>
    {       
        public int Compare(object x, object y)
        {
            IComparer myComparer = Comparer<DateTime>.Default as IComparer;
            return myComparer.Compare(x, y);
        }     
    }

(ただし、コレクションに DateTime 以外のアイテムがある場合、これは例外をスローします)

編集:

もう少しタイプセーフなものを実装することもできます。

  public class DateTimeComparer : IComparer<object>
    {       
        public int Compare(object x, object y)
        {
            if ( x is DateTime && y is DateTime )
            {
                return Comparer<DateTime>.Default.Compare((DateTime) x, (DateTime) y);
            }
            else
            {
                // handle the type mismatch
            }
        }     
    }
于 2009-09-03T19:31:32.270 に答える
1

キャストを削除して、コンパイラに.IComparerの代わりに選択させるだけですIComparer<T>

Comparer<T>IComparer<T>両方を実装してIComparerいるので、動作するはずです。

これは問題なく機能します。

ArrayList collection = new ArrayList {DateTime.Now.AddDays(1), DateTime.Now};
collection.Sort(Comparer<DateTime>.Default);
于 2009-09-03T19:13:52.887 に答える