将结构转换为 class 继承自同一接口
Cast a struct to a class inherits from the same Interface
关于是否有任何方法可以将结构转换为 class 的同事提出的挑战,这里是我们尝试过的示例
namespace ConsoleApplication22
{
class Program
{
static void Main(string[] args)
{
IFoo fooS = new FooStruct();
fooS.Val = 5;
FooClass foo =(FooClass) fooS;
}
}
public interface IFoo
{
int Val { get; set; }
}
public struct FooStruct : IFoo
{
public int Val { get; set; }
}
public class FooClass : IFoo
{
//public FooClass(int val)
//{
//}
private int val;
public int Val
{
get { return val; }
set { val = value; }
}
}
}
但是我们得到了一个无效的转换异常:D
假设接口是引用类型并且 class 是引用类型并且 class 实现接口
没有。
为您的 FooClass
创建一个采用 IFoo
实例的复制方法,并在那里执行必要的复制。
你不能通过接口在两者之间直接转换,这是不允许的,因为它们彼此没有直接关系(即继承)。
编译器可以捕捉到很多这种类型的东西,甚至不允许转换编译。如果编译器做不到,运行时会做。对于显式转换,运行时将在转换失败时抛出异常,对于隐式转换(仅限引用类型)的尝试,运行时 returns null 并且不会抛出异常。
类型检查实际上检查 FooStruct
是一个 FooClass
,它不可能是.
但是,您可以使用转换运算符在它们之间转换,使其看起来像转换
class Program
{
static void Main(string[] args)
{
FooStruct f = new FooStruct();
f.Val = 2;
FooClass f2 = (FooClass)f;
Console.Read();
}
}
class FooClass : IFoo
{
public static explicit operator FooClass(FooStruct f)
{
FooClass foo = new FooClass();
foo.Val = f.Val;
return foo;
}
public int Val { get; set; }
}
struct FooStruct : IFoo
{
public int Val { get; set; }
public static explicit operator FooStruct(FooClass f)
{
FooStruct foo = new FooStruct();
foo.Val = f.Val;
return foo;
}
}
// This interface has little use in this scenario.
interface IFoo
{
int Val { get; set; }
}
不要混淆转换和转换。此外,请注意将接口应用于 struct
类型,因为可能会发生装箱。
我能想到的最 hackish 的方法(也是你永远不应该使用的方法!)是通过使用 Marshal
:
public unsafe static TDest UnsafeCast<TDest, TSrc>(object source)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(TSrc))];
fixed (byte* b = buffer)
Marshal.StructureToPtr(source, new IntPtr(b), true);
fixed (byte* b = buffer)
return (TDest) Marshal.PtrToStructure(new IntPtr(b), typeof (TDest));
}
这实际上将保存在 FooClass
中的数据编组为 FooStruct
,这允许它 "cast" 从引用类型到值类型。
如果您使用 FooStruct
类型而不是泛型类型参数,您可以选择跳过第二个编组,方法是直接将缓冲区从缓冲区转换为 FooStruct
类型:
fixed (byte* b = buffer)
{
var s = (FooStruct*) b;
return *s;
}
需要 unsafe
编译器选项,并且应该 never ever 在任何类型的生产环境中完成 - 它非常慢并且不可预测。
关于是否有任何方法可以将结构转换为 class 的同事提出的挑战,这里是我们尝试过的示例
namespace ConsoleApplication22
{
class Program
{
static void Main(string[] args)
{
IFoo fooS = new FooStruct();
fooS.Val = 5;
FooClass foo =(FooClass) fooS;
}
}
public interface IFoo
{
int Val { get; set; }
}
public struct FooStruct : IFoo
{
public int Val { get; set; }
}
public class FooClass : IFoo
{
//public FooClass(int val)
//{
//}
private int val;
public int Val
{
get { return val; }
set { val = value; }
}
}
}
但是我们得到了一个无效的转换异常:D
假设接口是引用类型并且 class 是引用类型并且 class 实现接口
没有。
为您的 FooClass
创建一个采用 IFoo
实例的复制方法,并在那里执行必要的复制。
你不能通过接口在两者之间直接转换,这是不允许的,因为它们彼此没有直接关系(即继承)。
编译器可以捕捉到很多这种类型的东西,甚至不允许转换编译。如果编译器做不到,运行时会做。对于显式转换,运行时将在转换失败时抛出异常,对于隐式转换(仅限引用类型)的尝试,运行时 returns null 并且不会抛出异常。
类型检查实际上检查 FooStruct
是一个 FooClass
,它不可能是.
但是,您可以使用转换运算符在它们之间转换,使其看起来像转换
class Program
{
static void Main(string[] args)
{
FooStruct f = new FooStruct();
f.Val = 2;
FooClass f2 = (FooClass)f;
Console.Read();
}
}
class FooClass : IFoo
{
public static explicit operator FooClass(FooStruct f)
{
FooClass foo = new FooClass();
foo.Val = f.Val;
return foo;
}
public int Val { get; set; }
}
struct FooStruct : IFoo
{
public int Val { get; set; }
public static explicit operator FooStruct(FooClass f)
{
FooStruct foo = new FooStruct();
foo.Val = f.Val;
return foo;
}
}
// This interface has little use in this scenario.
interface IFoo
{
int Val { get; set; }
}
不要混淆转换和转换。此外,请注意将接口应用于 struct
类型,因为可能会发生装箱。
我能想到的最 hackish 的方法(也是你永远不应该使用的方法!)是通过使用 Marshal
:
public unsafe static TDest UnsafeCast<TDest, TSrc>(object source)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(TSrc))];
fixed (byte* b = buffer)
Marshal.StructureToPtr(source, new IntPtr(b), true);
fixed (byte* b = buffer)
return (TDest) Marshal.PtrToStructure(new IntPtr(b), typeof (TDest));
}
这实际上将保存在 FooClass
中的数据编组为 FooStruct
,这允许它 "cast" 从引用类型到值类型。
如果您使用 FooStruct
类型而不是泛型类型参数,您可以选择跳过第二个编组,方法是直接将缓冲区从缓冲区转换为 FooStruct
类型:
fixed (byte* b = buffer)
{
var s = (FooStruct*) b;
return *s;
}
需要 unsafe
编译器选项,并且应该 never ever 在任何类型的生产环境中完成 - 它非常慢并且不可预测。