[英]Converting a generic Span<T> to a specific instantiation (e.g. Span<int>) if it actually of that type at runtime
Consider the following C# code:考虑以下 C# 代码:
using System;
public static class C
{
public static int[] TryGetIntArray<T>(T[] x)
{
if (x is int[] arr) // ok
return arr;
return Array.Empty<int>();
}
public static Span<int> TryGetIntSpan<T>(Span<T> x)
{
if (x is Span<int> span) // An expression of type 'Span<T>' cannot be handled by a pattern of type 'Span<int>'.
return span;
return Span<int>.Empty;
}
}
The idea is to return the argument as a particular specialization of Span<T>
(in this case, Span<int>
) if the argument is actually of that type at runtime;这个想法是,如果参数在运行时实际上是该类型,则将参数返回为
Span<T>
的特定特化(在本例中为Span<int>
); otherwise, just return an empty span.否则,只返回一个空跨度。 We can see that this approach works with an array, but fails with a span.
我们可以看到这种方法适用于数组,但不适用于跨度。 Is there a workaround to do this with spans as well?
是否也有解决方法可以使用 span 来做到这一点?
If you can add where T: struct
, there's a method for that:如果你可以添加
where T: struct
,那么有一个方法:
public static Span<int> TryGetIntSpan<T>(Span<T> x)
where T : struct
{
if (typeof(T) == typeof(int))
return MemoryMarshal.Cast<T, int>(x);
return Span<int>.Empty;
}
Otherwise, here's another way:否则,这是另一种方式:
public static Span<int> TryGetIntSpan<T>(Span<T> x)
{
if (typeof(T) == typeof(int))
return MemoryMarshal.CreateSpan(ref Unsafe.As<T, int>(ref MemoryMarshal.GetReference(x)), x.Length);
return Span<int>.Empty;
}
It deconstructs and reconstructs the span, as you can't just use Unsafe.As
for this, since Span
is a ref
struct and therefore it's not usable as a type parameter.它解构和重建跨度,因为你不能只使用
Unsafe.As
。至于这个,因为Span
是一个ref
结构,因此它不能用作类型参数。
The if (typeof(T) == typeof(int))
check is optimized away by the JIT. JIT 优化了
if (typeof(T) == typeof(int))
检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.