[英]C# casting error on generics
I have a C# method where I am trying to use generics
as: 我有一个C#方法,尝试将
generics
用作:
unsafe private void PerformWindowLevel<T>(int lower, int upper, ref T[] pixels)
Somewhere along the function I have the following line: 在函数的某处,我有以下内容:
float shift = ... // some value
float scale = ... // some value
float val = ((float)pixels[i] + shift) * scale;
Here I get the error Cannot convert type 'T' to 'float'
. 在这里,我收到错误消息
Cannot convert type 'T' to 'float'
。
The method is called as: 该方法称为:
PerformWindowLevel<byte>(10, 100, ref pixels);
So I am converting a byte
type to float which should be possible. 所以我正在将
byte
类型转换为浮点数,这应该是可能的。 pixels
is a byte array declared as public byte[] pixels;
pixels
是声明为public byte[] pixels;
的字节数组public byte[] pixels;
and filled with valid values. 并填充有效值。
The problem is that T
doesn´t know anything about what it might be in your calling code, it´s just a generic type-parameter, that could also be string
or whatever which you (apparently) can´t cast to float
. 问题是
T
对调用代码中的内容一无所知,它只是一个通用的类型参数,也可以是string
,也可以是您(显然)无法转换为float
。 You´d need a generic constraint: 您需要一个通用约束:
unsafe private void PerformWindowLevel<T>(int lower, int upper, ref T[] pixels) where T: float
This still doesn´t work as you can´t use a struct (which float
is) as generic type-parameter. 这仍然无法正常工作,因为您无法将结构(
float
)用作通用类型参数。 Only interfaces or classes are allowed. 仅允许使用接口或类。
However this would only allow float
to be a valid generic parameter making the term generic quite - well - ungeneric . 但是,这只会使
float
成为有效的泛型参数,从而使术语泛型非常不泛型 。 This is why generics are completely wrong in your case. 这就是为什么泛型在您的情况下完全错误的原因。 When only one or two types are possible you should create a concrete method (or an overload) for that specific type.
如果只有一种或两种类型,则应为该特定类型创建一个具体方法(或重载)。 Generics on the other side state that every type (that satisfies the generic constraint which is indicated by a
where
) is possible, not just one. 另一方面,泛型指出,每种类型(满足用
where
指示的泛型约束)都是可能的,而不仅仅是一种。
You need to write a Seperate TypeConverter as at Compile Time the Compiler is unaware of Type T and whether it can be converted to float . 您需要编写一个单独的TypeConverter,因为在编译时编译器不知道T类型以及它是否可以转换为float类型。
you can use Convert.ChangeType Method to Convert 您可以使用Convert.ChangeType方法进行转换
public class ConvertTypeClass<T1,T2>
{
public T1 ConvertMethod(T2 val)
{
return (T1) (Convert.ChangeType(val, typeof(T1)));
}
}
Cannot convert type 'T' to 'float' indicates that the compiler simply doesn't know exactly what kind of data type that generic type parameter T
currently has. 无法将类型'T'转换为'float'表示编译器完全不知道泛型类型参数
T
当前具有哪种数据类型。 Any attempt to cast T
to other type except for object
(as base class of all objects) will result InvalidCastException
. 任何将
T
InvalidCastException
为object
(其他object
基类)以外的其他类型的尝试都将导致InvalidCastException
。
Hence, based from how generic type parameter works as explained above, the code can be written as this: 因此,根据上述通用类型参数的工作方式,代码可以这样编写:
unsafe private void PerformWindowLevel<T>(int lower, int upper, ref T[] pixels)
{
float shift = 3.0F; // some value
float scale = 5.0F; // some value
float val = (Convert.ToSingle((object)pixels[i]) + shift) * scale;
}
or include a check for byte
data type before performing cast: 或在执行强制转换之前包含对
byte
数据类型的检查:
unsafe private void PerformWindowLevel<T>(int lower, int upper, ref T[] pixels)
{
if (typeof(T) == typeof(byte))
{
float shift = 3.0F; // some value
float scale = 5.0F; // some value
float val = (Convert.ToSingle((object)pixels[i]) + shift) * scale;
}
}
Note that the generic itself should be completely independent of the type, so if type parameter T
intended to just accept byte
just use ref byte[] pixels
instead. 请注意,泛型本身应完全独立于类型,因此,如果类型参数
T
打算仅接受byte
,则请使用ref byte[] pixels
代替。
NB: About the message A type used as a constraint must be an interface, a non-sealed class or a type parameter , it can be explained where float
( System.Single
) itself is just a struct
, which is implicitly sealed
. 注意:关于消息用作约束的类型必须是接口,未密封的类或类型参数 ,可以解释为
float
( System.Single
)本身只是一个struct
(隐式sealed
。 A struct or sealed class can't be used as generic type parameter constraint, but you can constrain that T
is a struct . 不能将struct或密封类用作通用类型参数约束,但是可以约束
T
为struct 。 Currently valid constraints should be like this: 当前有效的约束应如下所示:
void GenericMethod<T>() where T: class // reference type constraint
void GenericMethod<T>() where T: struct {} // value type constraint
void GenericMethod<T>() where T: new() // public parameterless constructor constraint
void GenericMethod<T>() where T: IConvertible // interface constraint
void GenericMethod<T>() where T: BaseClass // base class constraint
More info: Constraints on Type Parameters 更多信息: 类型参数的约束
Similar issues: 类似问题:
Cannot implicitly convert type 'T' to 'Int' 无法将类型“ T”隐式转换为“ Int”
This is a known problem given that the basic arithmetic types do not have a common interface (eg INumeric) which you could use to restrict your method, via where T : INumeric. 鉴于基本算术类型没有公共接口(例如,INumeric),可通过T:INumeric来限制您的方法,因此这是一个已知问题。
There is, however, a slightly clumsy workaround, which does compile! 但是,有一个稍微笨拙的解决方法,可以编译! If you include your code within a typeof condition, the compiler is happy.
如果将代码包含在typeof条件中,则编译器很高兴。 For example:
例如:
private void PerformWindowLevel<T>(int lower, int upper, ref T[] pixels)
{
if ((typeof(T) == typeof(byte)) || (typeof(T) == typeof(int)))
{
float shift = 1;
float scale = 2;
float val = ((float)(object)pixels[0] + shift) * scale;
}
}
All you need to do, is to include in your surrounding if condition, as many types as you need! 您需要做的就是,如果需要的话,将其包含在您的周围环境中! As I say a bit clumsy, but it works!
正如我所说的那样笨拙,但它有效!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.