次の 2 つのジェネリック型があります。
interface IRange<T> where T : IComparable<T>
interface IRange<T, TData> : IRange<T> where T : IComparable<T>
^---------^
|
+- note: inherits from IRange<T>
ここで、これらのインターフェイスのコレクションの拡張メソッドを定義したいと思います。これらはどちらも、IRange<T>
またはその子孫であるためIRange<T>
、両方を処理する 1 つのメソッドを定義できることを望んでいました。このメソッドは、2 つの違いを処理する必要はなく、 からの共通部分のみを処理する必要があることに注意してくださいIRange<T>
。
したがって、私の質問は次のとおりです。
IEnumerable<T>
これら 2 つのタイプのいずれかのコレクション ( ) を処理する拡張メソッドを 1 つ定義できますか?
私はこれを試しました:
public static void Slice<T>(this IEnumerable<IRange<T>> ranges)
where T : IComparable<T>
IEnumerable<IRange<Int32, String>>
ただし、次のように を渡します。
IEnumerable<IRange<Int32, String>> input = new IRange<Int32, String>[0];
input.Slice();
次のコンパイラ エラーが表示されます。
エラー 1 'System.Collections.Generic.IEnumerable>' には 'Slice' の定義が含まれておらず、タイプ 'System.Collections.Generic.IEnumerable>' の最初の引数を受け入れる拡張メソッド 'Slice' が見つかりませんでした ( using ディレクティブまたはアセンブリ参照がありませんか?) C:\Dev\VS.NET\LVK\LVK.UnitTests\Core\Collections\RangeTests.cs 455 26 LVK.UnitTests
注:コンパイルできるとは思っていませんでした。co(ntra)-variance (どちらがどちらの方向であるかを知る必要がある日) について十分に理解していて、それがうまくいかないことを知っています。私の質問は、Slice 宣言を機能させるために何かできることがあるかどうかです。
わかりましたので、範囲インターフェイスの型を推測しようとしIEnumerable<R>
ましR
たIRange<T>
。
だから私はこれを試しました:
public static Boolean Slice<R, T>(this IEnumerable<R> ranges)
where R : IRange<T>
where T : IComparable<T>
これは私に同じ問題を与えます。
それで、これを微調整する方法はありますか?
そうでない場合、私の唯一のオプションは次のとおりです。
- 2 つの拡張メソッドを定義し、おそらくコレクションの 1 つを基本インターフェイスを含むコレクションに変換することによって、内部メソッドを内部的に呼び出しますか?
- C# 4.0 を待ちますか?
2 つのメソッドを定義する方法を以下に示します (注: まだ設計の初期段階にあるため、まったく機能しない可能性があります)。
public static void Slice<T>(this IEnumerable<IRange<T>> ranges)
where T : IComparable<T>
{
InternalSlice<T, IRange<T>>(ranges);
}
public static void Slice<T, TData>(this IEnumerable<IRange<T, TData>> ranges)
where T : IComparable<T>
{
InternalSlice<T, IRange<T, TData>>(ranges);
}
private static void Slice<T, R>(this IEnumerable<R> ranges)
where R : IRange<T>
where T : IComparable<T>
これが私の問題を示すサンプルプログラムコードです。
Main メソッドで呼び出しを Slice1 から Slice2 に変更すると、両方の使用法でコンパイラ エラーが発生することに注意してください。
using System;
using System.Collections.Generic;
namespace SO1936785
{
interface IRange<T> where T : IComparable<T> { }
interface IRange<T, TData> : IRange<T> where T : IComparable<T> { }
static class Extensions
{
public static void Slice1<T>(this IEnumerable<IRange<T>> ranges)
where T : IComparable<T>
{
}
public static void Slice2<R, T>(this IEnumerable<R> ranges)
where R : IRange<T>
where T : IComparable<T>
{
}
}
class Program
{
static void Main(string[] args)
{
IEnumerable<IRange<Int32>> a = new IRange<Int32>[0];
a.Slice1();
IEnumerable<IRange<Int32, String>> b = new IRange<Int32, String>[0];
b.Slice1(); // doesn't compile, and Slice2 doesn't handle either
}
}
}