【问题标题】:How to tell a constructor it should only use primitive types如何告诉构造函数它应该只使用原始类型
【发布时间】:2013-06-17 23:40:43
【问题描述】:

我创建了一个只能处理原始(或 ICloneable)类型的类

我想知道是否可以这样说:

 public myobject(primitiv original){...}

或者我真的需要为每个原始类型创建一个构造函数,例如:

 public myobject(int original){...}
 public myobject(bool original){...}
 ...

我想要实现的是创建一个具有 3 个公共属性 Value、Original 和 IsDirty 的对象。
该值将是原始的深层克隆,因此原始需要是原始的或 ICloneable

【问题讨论】:

  • 您确定“原始类型”是什么定义明确吗? C# 语言规范提到了“简单类型”(所有结构),并且还有一些附加的“预定义类型”,它们是引用类型(如 string)。
  • @JeppeStigNielsen 我可以告诉你的好问题,是的。但是 selfe made struct 让我有些头疼
  • 例如,您认为System.UIntPtr 是“原始类型”吗?在您的特定场景中,所谓的“原始类型”有什么特别之处?例如,您不能有DateTime 类型的Value 吗?这是一个不可变的值类型(顺便说一下,它没有实现ICloneable)。
  • @JeppeStigNielsen DateTime 将是 Value 但没有 System.UIntPtr 或任何其他指针,所以对于我想要传递的内容来说,原始词是错误的词?
  • 我在这里的一些答案中说string 是一种原始类型(这是相关的,因为它不是结构,因此它将是一个类原始类型)。然而,这方面的文档是矛盾的,一篇 MSDN 文章说它是原始的,另一篇说它不是。 SO中有一个关于此的问题:stackoverflow.com/questions/3965752/is-string-a-primitive-type - 最后,我同意人们说文档不一致的说法。当您开始使用它时,运行时会清楚地表明 stringnot 原始的。

标签: c# types .net-4.0 overloading


【解决方案1】:

C# 中的原始类型被定义为结构(在 .NET CLR 中通常实现为 ValueType)。我相信你有两个选择:

  1. 正如已经说过的:接收任何类型,检查每个可接受的类型,如果不匹配则抛出异常。
  2. 使您的类通用,使构造函数具有where T : struct 的约束(T 是类型参数)。这将捕获所有结构,而不仅仅是原始类型,但我认为这是您希望在没有手动检查和编译时检查的情况下最好的结果。当然,您可以将此约束与其他约束混合使用。

您可以结合上面的两个选项,在编译时完成一些检查,而在运行时完成一些检查。

【讨论】:

  • +1。这可能最终成为 OP 最实用的解决方案。其他人给出了这个解决方案,但你解释得最好。
【解决方案2】:

如果您想这样做来强制使用您的 API 的人使用此类类型(如果他们使用错误的类型,则通过编译时错误),恐怕无法做到。

但是,您可以在构造函数中接收object,评估其类型,然后抛出ArgumentException,以防参数既不是“原始”类型之一也不是实现ICloneable

编辑:这可能很有用。可以通过以下代码判断变量是否属于原始类型:

Type t = foo.GetType();
t.IsPrimitive; // so you don't have to do an evaluation for each primitive type.

【讨论】:

  • +1 但不要忘记在调用 foo.GetType() 之前检查 foo != null(可能还抛出 ArgumentNullException)。
  • 嗯,我知道这一点,但它并没有真正帮助实现myobject(primitiv original)
【解决方案3】:

这不是您所要求的,但您可以有 2 个构造函数,一个用于结构,一个用于 ICloneable:

 public myobject(System.ValueType original){...}
 public myobject(ICloneable original){...}

【讨论】:

  • DateTimeTimeSpan 不是原语,但会通过第一个构造函数。
  • @Renan 我知道这个问题提到了“原始”类型,但作者也提到他想要一个“原始的深度克隆”。
  • @Renan 哇,我认为它很原始,所以这个答案仍然适合,所以我将研究 ValueType
【解决方案4】:

泛型而不是反射怎么样?

public class MyObject<T>
    where T: IComparable
{
    public MyObject(T original)
    {
        // do runtime check
    }
}


var c1 = new MyObject<int>(1);
// or
var c2 = new MyObject<Int32>(2);

【讨论】:

  • 我如何要求原始?因为原始类型没有 ICloneable
  • Int32 没有实现 ICloneable for ex.
  • 所以将 IClonable 更改为 struct,因为有人已经指出原语被定义为结构。
  • @JuanAyala 但现在每个结构都可以传递这个构造函数......这不是我想要的
  • 是的,但就像 Theodoros 指出的那样,在没有手动检查的情况下,它是您所希望的最好的。在疯狂的一面,你可以尝试像这样约束你的类: public class MyObject where T : IComparable, IFormattable, IConvertible, IComparable, IEquatable where TBase : struct 但你必须创建一个这样的实例: var c1 = new MyObject(1);
猜你喜欢
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多