5

I created an Class which is only able to handle primitive (or ICloneable) Types

I want to know if it's possible to say something like:

 public myobject(primitiv original){...}

or do I really need to create a constructor for each primitive type like:

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

What I am trying to achieve is to create an object with 3 public properties Value, Original and IsDirty.
The Value will be an deep Clone of Original so the Original needs to be primitve or ICloneable

Joel in Gö
  • 7,460
  • 9
  • 47
  • 77
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
  • Are you sure it's well-defined what a "primitive type" is? The C# Language specification mentions "simple types" (all structs) and also has some additional "predefined types" which are reference types (like `string`). – Jeppe Stig Nielsen Jun 17 '13 at 14:12
  • @JeppeStigNielsen good question as far as i can tell you, yes. But selfe made struct are providing me some headaches – WiiMaxx Jun 17 '13 at 14:31
  • For example, do you consider `System.UIntPtr` a "primitive type"? What is so special about so-called "primitive types" in your specific scenario? Couldn't you have a `Value` of type `DateTime` for example? It's an immutable value type (and it does not implement `ICloneable` by the way). – Jeppe Stig Nielsen Jun 17 '13 at 15:05
  • @JeppeStigNielsen `DateTime`would be an `Value` but no `System.UIntPtr `or any other Pointer, so primitive would be the wrong word for what i want to pass? – WiiMaxx Jun 17 '13 at 20:16
  • 1
    I was saying in some comments on the answers here that `string` is a primitive type (which is relevant, since it's not a struct, therefore it would be a class primitive). However, the documentation for that is contradictory, with one MSDN articles saying it is primitive, and another saying it isn't. There was a question in SO about that: http://stackoverflow.com/questions/3965752/is-string-a-primitive-type - In the end, I agree with the people saying that documentation is inconsistent. When you get down to it, the runtime clearly says `string` is *not* primitive. – Geeky Guy Jun 17 '13 at 20:41
  • I would say string is not a primitive type (because `.IsPrimitive` says no). It is not a simple type in the definition of the C# specification either. But it _is_ a predefined type in C# because it's a type required for the compiler to work, it has its own reserved keyword `string` (lower-case s), and you can write compile-time literals and `const` variables of its type. – Jeppe Stig Nielsen Jun 18 '13 at 05:56

4 Answers4

6

If you want to do that to force whomever is using your API to use such types (through compile time errors should they use the wrong types), I'm afraid it can't be done.

You could, however, receive an object in the constructor, evaluate its type, and throw an ArgumentException in case the parameter is neither one of the "primitive" types nor implements ICloneable.

Edit: This might be useful. You can determine whether a variable belongs to a primitive type with the following code:

Type t = foo.GetType();
t.IsPrimitive; // so you don't have to do an evaluation for each primitive type.
Geeky Guy
  • 9,229
  • 4
  • 42
  • 62
  • 1
    +1 but don't forget to check that `foo != null` (and perhaps throwing `ArgumentNullException`) before calling `foo.GetType()`. –  Jun 17 '13 at 13:47
  • mhh i know this to but it doesn't really help to achieve `myobject(primitiv original)` – WiiMaxx Jun 17 '13 at 13:49
6

Primitive types in C# are defined as structs (implemented generally as ValueType in the .NET CLR). I believe you have two options:

  1. As has been said already: Receive any type, check it against every acceptable type, throw an exception if it doesn't match.
  2. Make your class generic, make the constructor generic with a constraint of where T : struct (with T being the type parameter). This will catch all structs, not just the primitive types, but I think that's the best you can hope for without manual checking and with compile-time checking. You can mix this constraint with other ones, of course.

And you can combine the two options above to have some of the checking be done at compile-time and some of it be done at run-time.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • +1. This may end up being the most practical solution for the OP. Other people gave that solution but you explained it best. – Geeky Guy Jun 17 '13 at 15:12
2

It is not exactly what you asked, but you can have 2 constructors, one for structs and one for ICloneable:

 public myobject(System.ValueType original){...}
 public myobject(ICloneable original){...}
Corneliu
  • 2,932
  • 1
  • 19
  • 22
  • `DateTime` and `TimeSpan` aren't primitives but would pass through that first constructor. – Geeky Guy Jun 17 '13 at 13:53
  • @Renan I know the question mentions the "primitive" types, but the author also mentioned that he wants a "deep Clone of Original". – Corneliu Jun 17 '13 at 13:57
  • @Renan wow i thought it is primitive so this Answer would still fit, so i will research about ValueType – WiiMaxx Jun 17 '13 at 14:00
-2

How about generics instead of reflection?

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);
Juan Ayala
  • 3,388
  • 2
  • 19
  • 24
  • and how do i ask for primitive? because primitive Types hasn't the ICloneable – WiiMaxx Jun 17 '13 at 13:51
  • 2
    Int32 does not implement ICloneable for ex. – Corneliu Jun 17 '13 at 13:52
  • so change IClonable to struct, as someone already pointed out primitives are defined as structs. – Juan Ayala Jun 17 '13 at 13:55
  • @JuanAyala but now every struct can pass this constructor ... thats not what i wan't – WiiMaxx Jun 17 '13 at 14:04
  • Yeah but like Theodoros pointed out, its the best you can hope for without manual checking. On the crazy side, you could try to constrain your class like this: public class MyObject where T : IComparable, IFormattable, IConvertible, IComparable, IEquatable where TBase : struct but you would have to create an instance like this: var c1 = new MyObject(1); – Juan Ayala Jun 17 '13 at 14:40
  • so perhaps doing an IComparable constraint along with a run time check as other ppl pointed out. the primitives should all implement IComparable. – Juan Ayala Jun 17 '13 at 15:27