【问题标题】:Multiple Type Variable C#多类型变量 C#
【发布时间】:2014-04-20 11:10:40
【问题描述】:

我在这里遇到了一个奇怪的问题。我有一个项目约束,其中属性的值需要是数字(intdoublelong 等都可以接受)、stringdatetime。 Value 参数需要是这三个之一的原因(错误..如果你计算所有可能的数值类型允许它多一点)类型是因为根据类型,基础值需要转换为用于序列化为 REST API 的特殊格式。为了简化这里的事情,将类作为 POCO 的基本思想:

class Foo
{
     public string Name {get;set;}
     public Guid Id {get; set;}
     public UNKNOWN Value {get;set;}
}

我考虑过为此使用泛型,并带有where T : struct 约束,但这仍然留下了太多理论上可以设置但实际上是无效类型的类型。当然,我可以在 Value 参数的构造/设置期间执行类型检查并抛出异常,但这感觉不像是“干净”的代码。

我查看了这个问题 How do you work with a variable that can be of multiple types? ,但它并没有真正帮助,因为它更多的是处理继承的问题。但是,使用多个可为空的私有字段并根据填充的属性返回单个属性是可能的,但我再次觉得必须有更好的方法。

我想到的另一种可能性是使用dynamic 类型并执行一些反射魔法来检查底层类型(并执行转换和格式化/抛出异常)。我有点害怕这会真的影响性能。

对于这种情况有什么最佳做法吗?如果没有,根据我提到的内容,有没有更好的方法来处理这个问题?

【问题讨论】:

  • 不要害怕dynamic。最后,您不会因为使用它而失眠。如果您使用dynamic Valueobject Value 创建测试,请使用秒表来对比从动态属性与对象的检索,并且必须强制转换为预期的类型。无论哪种方式,您都会冒着假设错误类型的风险。
  • @IAbstract 我肯定会尝试一下,但我更关心的是从反射方法中获取底层类型的性能损失,因此我可以执行必要的格式化它正在被序列化。
  • 不会在这个任务中使用dynamic;如果您希望“进行价值反射”,只需使用 Object(因为 dynamic 适合“方法调用的神奇后期绑定”) - 但是,如果可能的话,我建议您考虑沿 接口。有关类型转换,请参阅Type Converters,以及在 Json.NET 等各种库中完成的各种特殊情况。
  • @user2864740:同意;但是,不能保证某个接口可以解决此特定问题。 :)
  • @JNYRanger 我的建议是尽可能沿接口对齐。使用dynamic 表示Duck Typing - 使用Object 接受“任意类型”。

标签: c# generics dynamic types


【解决方案1】:

编辑 Eric Lippert 在他的一个史诗般的 stackoverflow 答案中教给我这种类型的调度,我现在正在寻找它。如果/当我找到它时,我会用一个链接更新这个答案(这个人已经回答了很多问题)。另外,OP,您询问了性能,请查看 Lippert 提供的此信息:How does having a dynamic variable affect performance?

我会混合使用动态和特殊情况处理,以及一个泛型类型来捕获所有未定义(尚未实现)的类型。

class Foo
{
  public dynamic Value { get; set; }
}

class FooHandler
{
  public void Serialize(Foo foo)
  {
    SerializeField(foo.Value);
  }

  void SerializeField(int field)
  {
    Console.WriteLine("handle int");
  }

  void SerializeField<T>(T field)
  {
    throw new NotImplementedException("Serialization not implemented for type: " + typeof(T));
  }
}

class Program
{
  [STAThread]
  static void Main(string[] args)
  {
    Foo f = new Foo();
    f.Value = 1;

    FooHandler handler = new FooHandler();
    handler.Serialize(f);

    Console.ReadKey();
  }
}

然后在闲暇时添加类型。

【讨论】:

  • 我仍然会在类型级别上使用object,但是在这里使用dynamic(动态后期绑定到正确的重载)可能非常实用; +1 显示这样的调度。
  • 哇,这成功了,并且在可读性方面非常优雅。我最终在扩展方法中实现了处理程序,该方法由自定义 JsonConverter(使用 Json.NET)调用。不需要使用任何反射,这是一件很美好的事情,也不需要额外的类型检查!如果您找到 Eric Lippert 的那篇文章,请将其发布,我很乐意看一看。
【解决方案2】:

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

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());
    }
}

【讨论】:

  • 我将它用于保存组件或控件的值,因为它们在 WinForms 中具有单独的继承树。简单但有效:)
猜你喜欢
  • 1970-01-01
  • 2015-10-23
  • 2016-08-30
  • 2015-06-21
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
相关资源
最近更新 更多