多类型变量C#

多类型变量C#,c#,generics,dynamic,types,C#,Generics,Dynamic,Types,我这里有点奇怪。我有一个项目约束,其中属性的值需要是一个数字(int,double,long,等等都可以接受),一个字符串,或者一个datetime。Value参数需要是这三种类型中的一种(err..如果您计算所有允许的可能的数值类型,它会多一点)的原因是,根据类型的不同,基础值需要转换为特殊格式,以便序列化为REST API。简化这里的内容是类作为POCO的一个基本概念: class Foo { public string Name {get;set;} public Gu

我这里有点奇怪。我有一个项目约束,其中属性的值需要是一个数字(
int
double
long
,等等都可以接受),一个
字符串
,或者一个
datetime
。Value参数需要是这三种类型中的一种(err..如果您计算所有允许的可能的数值类型,它会多一点)的原因是,根据类型的不同,基础值需要转换为特殊格式,以便序列化为REST API。简化这里的内容是类作为POCO的一个基本概念:

class Foo
{
     public string Name {get;set;}
     public Guid Id {get; set;}
     public UNKNOWN Value {get;set;}
}
我曾考虑过使用泛型来实现这一点,使用
where T:struct
约束,但这仍然会留下太多理论上可以设置的类型,而实际上这些类型是无效的。当然,我可以在构造/设置Value参数的过程中执行类型检查并抛出异常,但这不像是“干净”的代码

我看了一下这个问题,但它并没有真正起到帮助作用,因为它更像是一个处理继承的问题。然而,使用多个可为空的私有字段并返回一个基于其填充的属性是可能的,但我再次感到必须有更好的方法

我考虑的另一种可能性是使用
动态
类型,并执行一些反射魔法来检查底层类型(并执行转换和格式化/抛出异常)。不过,我有点担心这会真正影响性能


对于这种情况,有什么最佳做法吗?如果没有,有没有更好的方法来处理我刚才提到的问题呢?

编辑埃里克·利珀特(Eric Lippert)在他的一个史诗般的答案中教过我这种类型的调度,我正在寻找它。如果/当我找到这个答案时,我会用一个链接更新这个答案(这个人回答了很多问题)。还有,OP,你问到了性能问题,看看同样来自Lippert的信息:

我将混合使用带有特殊案例处理的dynamic和未定义(尚未实现)类型的泛型类型catch all

class-Foo
{
公共动态值{get;set;}
}
类foodhandler
{
公共void序列化(Foo-Foo)
{
序列化字段(foo.Value);
}
无效字段(整型字段)
{
控制台写入线(“句柄int”);
}
无效字段(T字段)
{
抛出新的NotImplementedException(“类型:+typeof(T)未实现序列化”);
}
}
班级计划
{
[状态线程]
静态void Main(字符串[]参数)
{
Foo f=新的Foo();
f、 数值=1;
FooHandler=新的FooHandler();
序列化(f);
Console.ReadKey();
}
}

然后在空闲时添加类型。

您可以使用专用类作为“多类型变量”。 在实例化时,您可以传递一个
int
double
long
,等等。当您需要取出存储值时,您可以使用单独的调用

public class Foo
{
    public class Value
    {
        object _value;
                
        public Value(int value) { _value = value; }
        public Value(double value) { _value = value; }
        public Value(long value) { _value = value; }
        // etc

        public object GetValue() { return _value; }
    }

    public void TestCall()
    {
        Value myValue = new Value(123);
        Debug.WriteLine(myValue.GetValue());
    }
}

不要害怕
动态
。最终,你不会因为使用它而失眠。如果使用
动态值
对象值
创建测试,请使用秒表对比从动态属性检索与对象以及必须转换为预期类型。不管是哪种方式,您都有可能假设预期的类型是错误的。@事实上,我一定会尝试一下,但是我更关心的是反射方法在获取底层类型时会对性能造成的影响,这样我就可以在序列化时执行必要的格式化;如果希望“进行值反射”(因为
dynamic
适用于“神奇的方法调用后期绑定”),只需使用
Object
——不过,如果可能的话,我建议您考虑沿接口进行统一。有关类型转换,请参阅,以及在各种库(如Json.NET)中执行的各种特殊大小写。@user2864740:Agreed;但是,接口不能保证解决此特定问题。:)@如果可能的话,我的建议是沿着接口对齐。使用
dynamic
for-使用
Object
接受“任意类型”。我仍然会在类型级别使用
Object
,但是使用
dynamic
(动态延迟绑定到正确的重载)在这里可能非常实用+感谢你展示这样一篇文章。哇,这真是个好主意,而且在可读性方面非常优雅。我最终在一个扩展方法中实现了该处理程序,该扩展方法由一个自定义JsonConverter(使用Json.NET)调用。不需要使用任何反射,这是一件漂亮的事情,也不需要额外的类型检查!如果你找到Eric Lippert的那篇文章,请发表,我很想看一看。我用这个值来表示一个组件或控件,因为它们在WinForms中有单独的继承树。简单但有效:)
public class Foo
{
    public class Value
    {
        object _value;
                
        public Value(int value) { _value = value; }
        public Value(double value) { _value = value; }
        public Value(long value) { _value = value; }
        // etc

        public object GetValue() { return _value; }
    }

    public void TestCall()
    {
        Value myValue = new Value(123);
        Debug.WriteLine(myValue.GetValue());
    }
}