如何将int []类型转换为int?[]

时间:2015-12-07 21:47:36

标签: c# linq extension-methods ienumerable nullable

我使用linq查询输出一个int数组。但是我需要将它传递给一个只接受int?[]的方法。

所以在搜索了将int []转换为int的方法之后?[]我找到了似乎可行的东西here

以下代码是一个简化示例,显示了哪些有效且无效。

using System;
using System.Collections.Generic;
using System.Web;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // working...
            int[] vids1 = new[] { "", "1", "2", "3" }
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .Select(x => Convert.ToInt32(x))
                .ToArray();

            foreach(int i in vids1) 
            {
                System.Diagnostics.Debug.WriteLine(i.ToString());
            }

            // not working...
            int?[] vids2 = new[] { "", "1", "2", "3" }
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .Select(x => Convert.ToInt32(x))
                .ToArrayOrNull();
        }
    }

    public static class IEnumerableExtensions
    {
        public static T?[] ToArrayOrNull<T>(this IEnumerable<T> seq)
        {
            var result = seq.ToArray();

            if (result.Length == 0)
                return null;

            return result;
        }
    }
}

我已经玩过这种扩展方法试图让它传回int?[]类型,但还没有运气。

如何让我的IEnumerable扩展ToArrayOrNull传回可以为空的类型?

5 个答案:

答案 0 :(得分:3)

int?[]int?的数组。您只需在Select中更改lambda,即可返回int?

int?[] vids2 = new[] { "", "1", "2", "3" }
    .Where(x => !String.IsNullOrWhiteSpace(x))
    .Select(x => (int?)Convert.ToInt32(x))
    .ToArray();

如果您已有int[],则可以使用Cast()将元素转换为int?

int[] ints = { 1, 2, 3 };
int?[] nullableInts = ints.Cast<int?>().ToArray();

答案 1 :(得分:2)

此扩展方法ToArrayOrNull不会更改内容的类型。 seqIEnumerable TresultT的数组(您有时会将其返回为null,但这仍然是T的数组。

如果你真的想要将IEnumerable<T>转换为IEnumerable<T?>(或T?数组),你应该对类型参数设置一些约束(它应该是{{1 },意思是一个值类型,一个不能为null),并转换每个项而不是整个结果,如:

struct

虽然我会在这里返回 public static T?[] ToArrayOfNullable<T>(this IEnumerable<T> seq) where T : struct { return seq.Select(val => (T?)val).ToArray(); } 并稍后转换为数组,但要保持此方法的简单。

答案 2 :(得分:1)

不要先做错事,然后再修好。做正确的事情straigtaway。你知道你需要一个int?[]。所以创建一个int?[]。不要先创建int[],然后再修复它。你可以让它发挥作用,但它毫无意义的复杂。

int?[] vids1 = new[] { "", "1", "2", "3" }
    .Where(x => !String.IsNullOrWhiteSpace(x))
    .Select(x => (int?) Convert.ToInt32(x))
    .ToArray();

我强烈建议您甚至不尝试让ToArrayOrNull工作的原因也是因为它甚至没有接近做你应该做的事情。你可以使它工作,但你必须了解在开始编码之前应该发生什么。只要你不需要它,现在就离开这个,当你回顾过去时,你可能会突然看到它。

答案 3 :(得分:1)

使用Cast<>以及使T成为struct的类型约束如何:

public static IEnumerable<T?> ToArrayOrNull<T>(this IEnumerable<T> seq)
    where T : struct
{
    if (seq.Count() == 0)
        return null;

    return seq.Cast<T?>().ToArray();
}

答案 4 :(得分:1)

我知道这不是你的问题的正确答案,但有一个不同的解决方案 - 如果你想保持订单和收集长度。

public static class EnumerableExtensions
{
    public delegate bool ParseDelegate<T>(string input, out T value) where T : struct;

    public static T?[] ToNullable<T>(this string[] values, ParseDelegate<T> parseMethod) where T : struct
    {
        IEnumerable<T?> cos = values.Select(s =>
        {
            T result;
            if (parseMethod(s, out result))
            {
                return (T?)result;
            }

            return null;
        });

        return cos.ToArray();
    }
}

用法:

var cos = new[] { "1", "", "3", "True" };
int?[] eee= cos.ToNullable<int>(int.TryParse); // 1, null, 3, null
float?[] ada = cos.ToNullable<float>(float.TryParse); // 1, null, 3, null
bool?[] asd3 = cos.ToNullable<bool>(bool.TryParse); // null, null, null, true