C# 将对象强制转换为泛型类型实例

C# 将对象强制转换为泛型类型实例,c#,.net,generics,casting,C#,.net,Generics,Casting,我有一个类选项定义如下: class Option<T> { T Value { get; set; } bool HasValue { get; } } 我想将值强制转换为选项,但在编译时我不知道类型t。 我如何“向上转换”实例,以便能够检查,例如,值属性?您在评论中告诉我们的唯一一件事是您希望访问HasValue。这很简单——创建一个接口 public interface IOption { bool HasValue { get; } } cla

我有一个类
选项
定义如下:

class Option<T>
{
     T Value { get; set; }
     bool HasValue { get; }
}
我想将值强制转换为
选项
,但在编译时我不知道类型
t

我如何“向上转换”实例,以便能够检查,例如,
属性?

您在评论中告诉我们的唯一一件事是您希望访问
HasValue
。这很简单——创建一个接口

public interface IOption
{
    bool HasValue { get; }
}

class Option<T> : IOption
{
     T Value { get; set; }
     bool HasValue { get; }
}

然后,您将能够将
对象
强制转换为
IOption
,并且它将成功转换为任何
T
,允许您将
作为
对象
检索。但是,您将无法设置它。

如果您知道所有可能的情况,您可以使用模式匹配:

        public static void Main(string[] args) 
        {
            object someOption = new Option<DateTime>() { Value = DateTime.Now};
            
            switch (someOption)
            {
                case Option<DateTime> dt: 
                    Console.WriteLine($"Date: {dt.Value}");
                    break;
                case Option<string> str:
                    Console.WriteLine($"String: {str}");
                    break;
            }
        }
publicstaticvoidmain(字符串[]args)
{
object someOption=new Option(){Value=DateTime.Now};
开关(选件)
{
案例选项dt:
WriteLine($“日期:{dt.Value}”);
打破
案例选项str:
WriteLine($“字符串:{str}”);
打破
}
}
否则,这可能是您的解决方案。有时,当我需要将对象传递给其他泛型方法或在泛型类型中使用它时,我会使用这样的conecpt

        interface IOptionHandler
        {
            void Handle(object option);
        }
        static class OptionHandler
        {
            public static IOptionHandler Create(Type targetType)
            {
                // normally you would check if it really is an Option<T> 
                // by providing some non-generic interface like IOption
                // we skip this part

                var typeParam = targetType.GetGenericArguments()[0];
                var helperType = typeof(Helper<>).MakeGenericType(typeParam);
                return (IOptionHandler) Activator.CreateInstance(helperType);
            }

            class Helper<T> : IOptionHandler
            {
                public void Handle(object option)
                {
                    // in this context you can use all the generic powers again
                    Option<T> myOlOption = (Option<T>) option;

                    List<Option<T>> whatever = new List<Option<T>>();
                    whatever.Add(myOlOption);

                    Console.WriteLine($"{myOlOption.Value.GetType()}: {myOlOption.Value}");
                }
            }
        }

        public static void Main(string[] args) 
        {
            object someOption = new Option<DateTime>() { Value = DateTime.Now};

            var handler = OptionHandler.Create(someOption.GetType());
            handler.Handle(someOption);
        }
接口IOptionHandler
{
无效句柄(对象选项);
}
静态类OptionHandler
{
公共静态IOptionHandler创建(类型targetType)
{
//通常你会检查它是否真的是一个选项
//通过提供一些非通用接口,如IOption
//我们跳过这一部分
var typeParam=targetType.GetGenericArguments()[0];
var helperType=typeof(Helper).MakeGenericType(typeParam);
return(IOptionHandler)Activator.CreateInstance(helperType);
}
类帮助程序:IOptionHandler
{
公共无效句柄(对象选项)
{
//在这种情况下,您可以再次使用所有通用权限
选项myOlOption=(选项)选项;
List whatever=新列表();
不管怎样,加上(肌肉发育);
WriteLine($“{myOlOption.Value.GetType()}:{myOlOption.Value}”);
}
}
}
公共静态void Main(字符串[]args)
{
object someOption=new Option(){Value=DateTime.Now};
var handler=OptionHandler.Create(someOption.GetType());
handler.Handle(someOption);
}

我通常会缓存创建的helper对象,但这完全取决于用例。

“我想将值强制转换为一个选项,但在编译时我不知道类型t”,然后您就不能强制转换,因为强制转换是一个编译时概念。您需要使用反射或
动态
。如果不知道类型,您希望如何检查
属性?你能给我们一个你想用
选项
对象做什么的片段吗?这个对象可能不是用C语言编译的,但传达了你的意图?如果你能改变类,用
对象值
属性实现一个非泛型的
IOption
接口。如果你不知道要转换到的类型,你应该如何转换。。。?不可能<代码>选项只是一个类型的蓝图。在运行时,
T
是一个实际类型。那么,如何使用反射来检查HasValue呢?我忘了说Option是第三方类,所以我不能让它实现任意接口。
        public static void Main(string[] args) 
        {
            object someOption = new Option<DateTime>() { Value = DateTime.Now};
            
            switch (someOption)
            {
                case Option<DateTime> dt: 
                    Console.WriteLine($"Date: {dt.Value}");
                    break;
                case Option<string> str:
                    Console.WriteLine($"String: {str}");
                    break;
            }
        }
        interface IOptionHandler
        {
            void Handle(object option);
        }
        static class OptionHandler
        {
            public static IOptionHandler Create(Type targetType)
            {
                // normally you would check if it really is an Option<T> 
                // by providing some non-generic interface like IOption
                // we skip this part

                var typeParam = targetType.GetGenericArguments()[0];
                var helperType = typeof(Helper<>).MakeGenericType(typeParam);
                return (IOptionHandler) Activator.CreateInstance(helperType);
            }

            class Helper<T> : IOptionHandler
            {
                public void Handle(object option)
                {
                    // in this context you can use all the generic powers again
                    Option<T> myOlOption = (Option<T>) option;

                    List<Option<T>> whatever = new List<Option<T>>();
                    whatever.Add(myOlOption);

                    Console.WriteLine($"{myOlOption.Value.GetType()}: {myOlOption.Value}");
                }
            }
        }

        public static void Main(string[] args) 
        {
            object someOption = new Option<DateTime>() { Value = DateTime.Now};

            var handler = OptionHandler.Create(someOption.GetType());
            handler.Handle(someOption);
        }