Можно ли отличить тип в штучной упаковке от ссылочного типа без отражения? - PullRequest
1 голос
/ 27 февраля 2012

Если есть подпрограмма, которая принимает параметр типа IEnumerator<string>, есть ли способ отличить ссылку на экземпляр типа класса от ссылки на экземпляр типа значения в штучной упаковке? Я знаю, что если у вас есть рутина, как:

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

Можно определить, является ли T типом значения или ссылочным типом, без использования отражения, просто выполнив Object.ReferenceEquals(param, param). Это всегда будет возвращать true, если T является типом класса, и всегда возвращать false, если это тип значения (это не может быть типом значения, допускающим значение NULL, поскольку он реализует интерфейс). С другой стороны, если бы кто-то позвонил DoSomething<IEnumerator<string>>(myListOfStrings.GetEnumerator()), я не знаю, каким образом DoSomething смог бы без использования Reflection отличить поведение в штучной упаковке IEnumerator<string> от поведения любого другого типа класса. Есть ли какой-либо не связанный с Reflection способ, которым поведение типов значений в штучной упаковке отличается от поведения типов классов?

Добавление

Чтобы прояснить вопрос, предположим, что у меня есть структура S1, которая реализует IFoo, и у меня есть класс C1, который реализует тот же интерфейс и имеет точно такие же методы и поля. Если есть переменная объявленного типа IFoo, есть ли способ, которым «естественное» поведение экземпляра S1 в штучной упаковке, на которое ссылается эта переменная, будет отличаться от поведения C1, на который ссылаются, аналогично , кроме тот факт, что GetType (), конечно, будет возвращать различные Type объекты ?

Ответы [ 3 ]

4 голосов
/ 27 февраля 2012

Если у вас есть объект e, статическим типом которого является некоторый интерфейс (например, IEnumerator<string>), и вы хотите узнать, является ли он типом в штучной упаковке, вы можете просто использовать:

e is ValueType

System.ValueType - это общий базовый класс всех типов значений в .Net.

0 голосов
/ 08 июня 2013

Я не знаю, будет ли это считаться «видимой разницей», но я думаю, что примечательно, что когда структура упакована в два раза, два объекта в штучной упаковке не будут равны ссылкам.Это имеет смысл, потому что структуры не имеют чувства ссылочной идентичности.Я не думаю, что это может произойти, однако.

Мой пример ниже довольно надуманный.

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);
        }
    }
}
0 голосов
/ 27 февраля 2012

Вы можете использовать свойство 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);
    }
...