数组的通用扩展方法无法编译

Kon*_*ski 4 c# arrays generics extension-methods .net-3.5

填充Web服务的请求对象,我需要动态地将项添加到某些数组.

我希望通过实现扩展方法来简化它:

public static class ArrayExtensions<T> where T : class
{
    public static T[] Extend<T>(T[] originalArray, T addItem)
    {
        if (addItem == null)
        {
            throw new ArgumentNullException("addItem");
        }
        var arr = new[] { addItem };
        if (originalArray == null)
        {
            return arr;
        }
        return originalArray.Concat(arr).ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个旧代码:

if (foo.bazArr == null)
{
    foo.bazArr  = new[] { baz };
}
else
{
    foo.bazArr = new[] { baz }.Concat(foo.bazArr).ToArray(); // (i know this inserts the new item at the beginning, but that's irrelevant, order doesn't matter)
}
Run Code Online (Sandbox Code Playgroud)

可以改写为:

foo.bazArr = foo.bazArr.Extend(baz); // won't compile
Run Code Online (Sandbox Code Playgroud)

错误是: 'System.Array' does not contain a definition for 'Extend' and no extension method 'Extend' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

而直接调用扩展方法是这样的:

foo.bazArr = ArrayExtensions<someService.bazType>.Extend(foo.bazArr, baz);
Run Code Online (Sandbox Code Playgroud)

编译好.

为什么会这样?如果数组是强类型的,为什么编译器不能在这里推断出类型呢?


编辑 - 正确的代码如下:

public static class ArrayExtensions
{
    public static T[] Extend<T>(this T[] originalArray, T addItem) where T : class
    {
        if (addItem == null)
        {
            throw new ArgumentNullException("addItem");
        }
        var arr = new[] { addItem };
        if (originalArray == null)
        {
            return arr;
        }
        return originalArray.Concat(arr).ToArray(); // although Concat is not recommended for performance reasons, see the accepted answer
    }
}
Run Code Online (Sandbox Code Playgroud)

对于这个流行的问题,这是另一个很好的简单例子:

public static class Extns
    {
    // here's an unbelievably useful array handling extension for games!

    public static T AnyOne<T>(this T[] ra) where T:class
        {
        int k = ra.Length;
        int r = Random.Range(0,k);
        return ra[r];
        // (add your own check, alerts, etc, to this example code)
        }
    }
Run Code Online (Sandbox Code Playgroud)

并在使用中..

someArrayOfSoundEffects.AnyOne().Play();
someArrayOfAnimations.AnyOne().BlendLeft();
winningDisplay.text = successStringsArray.AnyOne() +", " +playerName;
SpawnEnormousRobotAt( possibleSafeLocations.AnyOne() );
Run Code Online (Sandbox Code Playgroud)

等等.对于任何数组,它将为您提供一个随机项.在游戏中经常使用随机效果等.阵列可以是任何类型.

Mar*_*ell 5

遗失this:

public static T[] Extend<T>(this T[] originalArray, T addItem)
Run Code Online (Sandbox Code Playgroud)

没有this 它不是一种扩展方法.

附加说明:一次扩展一个项目是很昂贵的.A List<T>会更好.检查您的Web服务工具是否提供列表作为选项.

即使使用阵列,使用Enumerable.Concat在这里也可能过度; 我只是测量两个数组,分配一个新数组,并使用CopyTo每个数组的方法在新数组中写入.