如何在 C# 中将具有 `object` 类型的变量转换为具有泛型类型的 class?
How can I cast a variable with the `object` type to class with generic type in c#?
我有一个用 C# 编写的项目。我正在尝试将一个对象转换为接受枚举对象作为通用参数的 class。
我有以下class
public class GenericEnumViewModel<TEnum> where TEnum : struct
{
[Required]
public TEnum? Value { get; set; }
public IEnumerable<SelectListItem> Options { get; set; }
}
这是我的枚举对象之一的示例
public enum TestEnum
{
First,
Second,
Third,
Fourth
}
最后,我有一个 object
类型的变量
object obj = new GenericEnumViewModel<TestEnum>(); // Notice at this point I don't know that the generic type is `TestEnum` it could be any Enum.
如何检查变量 obj
是否实现了 GenericEnumViewModel<Enum>
?另外,如何创建一个名为 castedObj
的新变量作为 GenericEnumViewModel<Enum>
我正在尝试访问 castedObj.Value
和 castedObj.Options
。
我希望能够做这样的事情
var castedObj = obj as GenericEnumViewModel<Enum>;
if(castedObj != null)
{
// do something with castedObj.Value and castedObj.Options.
}
您可以添加新接口并显式实现它。然后你可以使用 C# 7.0 中引入的模式匹配。
public interface IGenericEnumViewModel
{
object Value { get; set; }
GenericEnumViewModel<SelectListItem> Options { get; set; }
}
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct
{
public TEnum? Value { get; set; }
public GenericEnumViewModel<SelectListItem> Options { get; set; }
object IGenericEnumViewModel.Value {
get {return Value;}
set {Value = (TEnum?)value;}
}
然后:
if(obj is IGenericEnumViewModel c)
{
//c is IGenericEnumViewModel
}
How can I check if the variable obj implements GenericEnumViewModel ?
你可以使用反射来做到这一点:
object obj = new GenericEnumViewModel<TestEnum>();
var objType = obj?.GetType();
var enumType =
objType != null && objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(GenericEnumViewModel<>) ?
objType.GetGenericArguments()[0] :
throw new InvalidOperationException($"Object is not a closed type of {typeof(GenericEnumViewModel<>).FullName}");
Also how can I make a new variable called castedObj as GenericEnumViewModel
由于多种原因,这是不可能的。以下行将无法编译:
// this code is invalid!
GenericEnumViewModel<Enum> model = new GenericEnumViewModel<TestEnum>();
首先,covariance 只允许在 C# 中用于接口、数组和委托。
此外,即使 classes 允许协方差,System.Enum is a reference type while enums are value types. Assigning an enum value to a System.Enum variable involves boxing。这本身会使上述任务变得不可能。
但是,您可以借助非通用接口(或抽象基 class)解决此问题,如下所示:
public interface IGenericEnumViewModel
{
Enum Value { get; }
GenericEnumViewModel<SelectListItem> Options { get; }
}
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct
{
[Required]
public TEnum? Value { get; set; }
public GenericEnumViewModel<SelectListItem> Options { get; set; }
Enum IGenericEnumViewModel.Value => Value.HasValue ? Value.Value : (Enum)null;
}
// ...
if (obj is IGenericEnumViewModel castedObj)
{
// do something with castedObj.Value and castedObj.Options.
Enum value = castedObj.Value;
// ...
}
奖金
从 C# 7.3 开始 you can use Enum in generic type constraints!
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct, Enum
{
// ...
}
我有一个用 C# 编写的项目。我正在尝试将一个对象转换为接受枚举对象作为通用参数的 class。
我有以下class
public class GenericEnumViewModel<TEnum> where TEnum : struct
{
[Required]
public TEnum? Value { get; set; }
public IEnumerable<SelectListItem> Options { get; set; }
}
这是我的枚举对象之一的示例
public enum TestEnum
{
First,
Second,
Third,
Fourth
}
最后,我有一个 object
类型的变量
object obj = new GenericEnumViewModel<TestEnum>(); // Notice at this point I don't know that the generic type is `TestEnum` it could be any Enum.
如何检查变量 obj
是否实现了 GenericEnumViewModel<Enum>
?另外,如何创建一个名为 castedObj
的新变量作为 GenericEnumViewModel<Enum>
我正在尝试访问 castedObj.Value
和 castedObj.Options
。
我希望能够做这样的事情
var castedObj = obj as GenericEnumViewModel<Enum>;
if(castedObj != null)
{
// do something with castedObj.Value and castedObj.Options.
}
您可以添加新接口并显式实现它。然后你可以使用 C# 7.0 中引入的模式匹配。
public interface IGenericEnumViewModel
{
object Value { get; set; }
GenericEnumViewModel<SelectListItem> Options { get; set; }
}
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct
{
public TEnum? Value { get; set; }
public GenericEnumViewModel<SelectListItem> Options { get; set; }
object IGenericEnumViewModel.Value {
get {return Value;}
set {Value = (TEnum?)value;}
}
然后:
if(obj is IGenericEnumViewModel c)
{
//c is IGenericEnumViewModel
}
How can I check if the variable obj implements GenericEnumViewModel ?
你可以使用反射来做到这一点:
object obj = new GenericEnumViewModel<TestEnum>();
var objType = obj?.GetType();
var enumType =
objType != null && objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(GenericEnumViewModel<>) ?
objType.GetGenericArguments()[0] :
throw new InvalidOperationException($"Object is not a closed type of {typeof(GenericEnumViewModel<>).FullName}");
Also how can I make a new variable called castedObj as GenericEnumViewModel
由于多种原因,这是不可能的。以下行将无法编译:
// this code is invalid!
GenericEnumViewModel<Enum> model = new GenericEnumViewModel<TestEnum>();
首先,covariance 只允许在 C# 中用于接口、数组和委托。
此外,即使 classes 允许协方差,System.Enum is a reference type while enums are value types. Assigning an enum value to a System.Enum variable involves boxing。这本身会使上述任务变得不可能。
但是,您可以借助非通用接口(或抽象基 class)解决此问题,如下所示:
public interface IGenericEnumViewModel
{
Enum Value { get; }
GenericEnumViewModel<SelectListItem> Options { get; }
}
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct
{
[Required]
public TEnum? Value { get; set; }
public GenericEnumViewModel<SelectListItem> Options { get; set; }
Enum IGenericEnumViewModel.Value => Value.HasValue ? Value.Value : (Enum)null;
}
// ...
if (obj is IGenericEnumViewModel castedObj)
{
// do something with castedObj.Value and castedObj.Options.
Enum value = castedObj.Value;
// ...
}
奖金
从 C# 7.3 开始 you can use Enum in generic type constraints!
public class GenericEnumViewModel<TEnum> : IGenericEnumViewModel where TEnum : struct, Enum
{
// ...
}