可以将盒装值类型与没有Reflection的引用类型区分开来

时间:2012-02-26 20:53:41

标签: .net struct boxing

如果有一个例程采用IEnumerator<string>类型的参数,是否有任何方法可以区分对类型实例的引用和对盒装值类型实例的引用?我知道,如果有一个例程:

void DoSomething<T>(T param) where T:IEnumerator

可以通过简单地执行T来判断Object.ReferenceEquals(param, param)是值类型还是引用类型而不使用反射。如果T是类类型,那么它将始终返回true,如果它是值类型,则它总是返回false(它不能是可为空的值类型,因为它实现了一个接口)。另一方面,如果有人打电话给DoSomething<IEnumerator<string>>(myListOfStrings.GetEnumerator()),我不知道DoSomething能够做什么,而不使用反射,区分盒装IEnumerator<string>的行为。任何其他类类型。是否存在与反射相关的方法,其中盒装值类型的行为与类类型的行为不同?

附录

为了澄清这个问题,假设我有一个实现S1的结构IFoo,并且我有一个实现相同接口的类C1,并且具有完全相同的方法和字段。如果有一个声明类型为IFoo的变量,那么该变量引用的盒装S1实例的“自然”行为是否会与引用的C1实例的行为不同?同样除了GetType()当然会返回不同的Type个对象这个事实?

3 个答案:

答案 0 :(得分:4)

如果您的对象e的静态类型是某个界面(如IEnumerator<string>),并且您想知道它是否为盒装值类型,则只需使用:

e is ValueType

System.ValueType是.Net中所有值类型的通用基类。

答案 1 :(得分:0)

您可以使用Type.IsValueType属性。这是一个例子:

    static void Main()
    {
        DoSomething(10);            // True
        DoSomething((object)10);    // True
        DoSomething(new Random());  // False
    }

    public static void DoSomething<T>(T arg)
    {
        bool isValueType = arg.GetType().IsValueType;
        Console.WriteLine(isValueType);
    }

答案 2 :(得分:0)

我不知道这是否会被视为“可见差异”,但我认为值得注意的是,当一个结构体被装箱两次时,两个盒装对象将不会是引用相等的。这是有道理的,因为结构没有引用 - 认同感。不过,我认为这不太可能出现。

下面我的例子非常人为。

public class BoxDemo
{
    public interface IFoo { }
    public class CFoo : IFoo { }
    public struct SFoo : IFoo { }

    public static class TestBoxing
    {
        public static void dotest()
        {
            CFoo C = new CFoo();
            SFoo S = new SFoo();

            Debug.WriteLine(IsBoxedStruct(C, C)); // writes "false"
            Debug.WriteLine(IsBoxedStruct(S, S)); // writes "true"
        }

        public static bool IsBoxedStruct(IFoo f1, IFoo f2)
        {
            return !object.ReferenceEquals(f1, f2);
        }
    }
}