可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using a linq query to output an int array. But I need to pass this into a method that only accepts int?[].
So after searching on ways to convert int[] to int?[] I found something that seemed might work here
The following code is a simplified example that shows what is working and not working.
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;
}
}
}
I've played around with this extension method trying to get it to pass back int?[] type, but no luck as of yet.
How can I get my IEnumerable extension ToArrayOrNull
to pass back nullable types?
回答1:
Don't do the wrong thing first, and then fix it up afterwards. Do the right thing straigtaway. You know you need an int?[]
. So create an int?[]
. Don't first create an int[]
and then fix it up. You can get it to work, but it's pointlessly complicated.
int?[] vids1 = new[] { "", "1", "2", "3" }
.Where(x => !String.IsNullOrWhiteSpace(x))
.Select(x => (int?) Convert.ToInt32(x))
.ToArray();
The reason I'm strongly suggesting not even trying to make your ToArrayOrNull
work is also because it doesn't even come close to doing what you're saying it should do. You can make it work, but you have to understand what's supposed to be going on before starting on your coding. Leave this for now as long as you don't need it anyway, and when you look back later you'll probably suddenly see it.
回答2:
int?[]
is an array of int?
. All you need is change lambda in Select
, to return an int?
:
int?[] vids2 = new[] { "", "1", "2", "3" }
.Where(x => !String.IsNullOrWhiteSpace(x))
.Select(x => (int?)Convert.ToInt32(x))
.ToArray();
If you already have an int[]
, you can use Cast()
to cast the elements to int?
int[] ints = { 1, 2, 3 };
int?[] nullableInts = ints.Cast<int?>().ToArray();
回答3:
This extension method, ToArrayOrNull
, does not change the type of the contents. seq
is an IEnumerable
of T
. result
is an array of T
(which you sometimes return as null
, but that's still an array of T
.
If you really want to convert an IEnumerable<T>
to an IEnumerable<T?>
(or an array of T?
), you should put some constraints on the type parameter (it should be struct
, meaning a value type, one that cannot be null), and convert each item instead of the whole result, something like:
public static T?[] ToArrayOfNullable<T>(this IEnumerable<T> seq)
where T : struct
{
return seq.Select(val => (T?)val).ToArray();
}
Although I would return an IEnumerable<T?>
here and convert to an array later, to keep this method simple.
回答4:
How about this using Cast<>
and a type constraint making T
a 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();
}
回答5:
I know that it's not correct answer for your question but there is a bit different solution - if you want to keep order and collection length.
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();
}
}
usage:
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