Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法推断C#类型参数_C#_Arrays_Generics - Fatal编程技术网

无法推断C#类型参数

无法推断C#类型参数,c#,arrays,generics,C#,Arrays,Generics,学习泛型。。我有一个通用数组处理程序,它允许对特定类型进行各种数组操作。我被告知使用T上的一个约束对测试数据进行排序,该约束带有IComparable,但我不知道该把条件放在哪里,所以我只使用了sort,它使用IComparable(即使它得到了结果,也可能不是我应该得到的结果) 无论如何,我还有一个方法来提取数组的一部分,这就是错误出现的地方。 比如这个: CS0411:方法“ArrayHelper_T.GetSubArray(T[],int,int)”的类型参数不能为空 从用法推断。尝试显式

学习泛型。。我有一个通用数组处理程序,它允许对特定类型进行各种数组操作。我被告知使用T上的一个约束对测试数据进行排序,该约束带有
IComparable
,但我不知道该把条件放在哪里,所以我只使用了
sort
,它使用
IComparable
(即使它得到了结果,也可能不是我应该得到的结果)

无论如何,我还有一个方法来提取数组的一部分,这就是错误出现的地方。 比如这个:

CS0411:方法“ArrayHelper_T.GetSubArray(T[],int,int)”的类型参数不能为空 从用法推断。尝试显式指定类型参数

如果我使用另一个我注释掉的(Program/Main),我会得到一个不同的错误,我也不知道如何修复。 我阅读了关于泛型和接口的msdn,并在这里查看了类似的错误问题,但它并没有帮助我找到解决方案

class Program
{
    static void Main(string[] args)
    {
        ArrayHelper_T<string> strings = new ArrayHelper_T<string>(size: 5);
        strings[0] = "cc";
        strings[1] = "bb";
        strings[2] = "aa";
        strings[3] = "ee";
        strings[4] = "dd";

        strings.SortPrintArray();

        int sub_start_index = 1;
        int sub_length = 3;
            
        ArrayHelper_T<string> sub_strings = new ArrayHelper_T<string>(sub_length);
        
        sub_strings = strings.GetSubArray(array: strings, index: sub_start_index, size: sub_length);
            
        //sub_strings = strings.GetSubArray<ArrayHelper_T<string>>
        //      (array: strings, index: sub_start_index, size: sub_length);
            
        sub_strings.SortPrintArray();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
ArrayHelper\u T字符串=新的ArrayHelper\u T(大小:5);
字符串[0]=“cc”;
字符串[1]=“bb”;
字符串[2]=“aa”;
字符串[3]=“ee”;
字符串[4]=“dd”;
strings.sortpintarray();
int sub_start_index=1;
int sub_长度=3;
ArrayHelper\u T sub\u字符串=新的ArrayHelper\u T(sub\u长度);
sub_strings=strings.GetSubArray(数组:strings,索引:sub_start_index,大小:sub_length);
//sub_strings=strings.GetSubArray
//(数组:字符串,索引:sub_start_index,大小:sub_length);
sub_strings.sortpritarray();
}
}
公共类数组帮助
//其中T:i可比较
//,i数不清
{
私有T[]数组;
公共阵列帮助(内部大小)
{
数组=新的T[大小];
}
公共T此[int索引]
{
获取{返回数组[索引];}
set{array[index]=value;}
}
公共整数大小
{
获取{return array.Length;}
}
public void SortPrintArray()//其中T:IComparable
{
如果(array.Length>1)
{
排序(数组);
WriteLine($”排序子向量:{string.Join(“,array)}.\n”);
}
其他的
WriteLine($“只有一个元素:{array[0]}.\n”);
}
公共T[]GetSubArray(T[]数组,整数索引,整数大小)
{
如果(!(数组为空)&&(索引>=0&&index(size您正在为类和on方法使用泛型类型参数,并且将它们混合在一起

正确的类型声明应该是

public class ArrayHelper_T<T> : IReadOnlyList<T>
    where T : IComparable<T>
{
    private IReadOnlyList<T> array;

    ...

    public void SortPrintArray()
    {
        ...
    }

    public T[] GetSubArray( int index, int size)
    {
        ...
    }
}
public类数组帮助:IReadOnlyList
其中T:i可比较
{
私有IReadOnlyList数组;
...
公共无效SortPrintArray()
{
...
}
公共T[]GetSubArray(整数索引,整数大小)
{
...
}
}
另一个非常适合本例的替代方法是使用扩展方法。这跳过了将数组封装在类中的需要,同时仍然允许您调用方法,就像调用实例方法一样

public static class ArrayHelper
{
    public static void SortPrintArray<T>(this T[] array) where T : IComparable<T>
    {
        ...
    }

    public static T[] GetSubArray<T>(this T[] array, int index, int size)
    {
        ...
    }
}
公共静态类ArrayHelper
{
公共静态void SortPrintArray(此T[]数组),其中T:IComparable
{
...
}
公共静态T[]GetSubArray(此T[]数组,int索引,int大小)
{
...
}
}
您可能还希望实现一个重载,该重载接受IComparer对象。这可能很有用,因为它允许调用方指定如何比较对象。例如,通过比较对象的某些属性而不是对象本身

public class KeyComparer<T, TKey> : IComparer<T> where TKey : IComparable<TKey>
{
    private readonly Func<T, TKey> selector;
    public KeyComparer(Func<T, TKey> selector) => this.selector = selector;
    public int Compare(T x, T y) => selector(x).CompareTo(selector(y));
}
 public static void SortPrintArray<T, TKey>(this T[] array, Func<T, TKey> selector) where TKey : IComparable<TKey>
        => SortPrintArray(array, new KeyComparer<T, TKey>(selector));
 public static void SortPrintArray<T>(this T[] array, IComparer<T> comparer) 
 {
        //...
  }
公共类KeyComparer:IComparer其中TKey:IComparable
{
专用只读函数选择器;
公钥比较器(Func选择器)=>this.selector=选择器;
公共int比较(tx,ty)=>选择器(x).CompareTo(选择器(y));
}
公共静态void SortPrintArray(此T[]数组,Func选择器),其中TKey:IComparable
=>SortPrintArray(数组,新的键比较器(选择器));
公共静态void SortPrintArray(此T[]数组,IComparer比较器)
{
//...
}

strings
if类型为
ArrayHelper\T
,但您希望在
GetSubArray
上有一个数组(
T[]
)。您的第二个问题是:如果您的类实现了ICollection,这将起作用。或者更一般地说(对于第二个问题),如果您的类实现了
IEnumerable
IEnumerable
,并且有一个带有适当签名的
Add
方法。您还可以有多个
Add
重载,并允许对初始化进行更改。这就是所谓的集合初始化模式:列出一个错误。它在哪一行ear?您有这个代码,声明
sub\u strings
ArrayHelper\u T sub\u strings
。然后,下一行是:
sub\u strings=strings.GetSubArray(params)
。但是,
GetSubArray
返回一个
T[]
,而不是
ArrayHelper\u T
谢谢你的示例。我尝试了你的第一个块,但它迫使我将
sortpritarray
更改为仅接受数组。这是一个问题,因为我在初始对象包装数组上也使用了相同的函数(代码段中没有)。遗憾的是,对于我的泛型初学者来说,第三个块看起来太复杂了。@zsombor V如果您想对数组以外的其他类型的列表使用相同的函数,我建议使用接口行
IReadOnlyList
,实现相同的接口,形成所谓的装饰器也可能有用。更新了示例以显示这
public class KeyComparer<T, TKey> : IComparer<T> where TKey : IComparable<TKey>
{
    private readonly Func<T, TKey> selector;
    public KeyComparer(Func<T, TKey> selector) => this.selector = selector;
    public int Compare(T x, T y) => selector(x).CompareTo(selector(y));
}
 public static void SortPrintArray<T, TKey>(this T[] array, Func<T, TKey> selector) where TKey : IComparable<TKey>
        => SortPrintArray(array, new KeyComparer<T, TKey>(selector));
 public static void SortPrintArray<T>(this T[] array, IComparer<T> comparer) 
 {
        //...
  }