25

There is an overload of Convert.ToInt32 that takes Int32 as the parameter. But even the documentation says that basically nothing happens and the method returns its input.

The question is why do we have such overload? Is there any purpose of it? Can anyone give me an example of using this method?

My thoughts: I think we may have it because there is an overload that takes Object. And thus we want to eliminate boxing and so on. But I'm not sure.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
Alex Sikilinda
  • 2,928
  • 18
  • 34
  • 7
    We have [`string.ToString()`](http://stackoverflow.com/questions/2778827/c-why-does-the-string-type-have-a-tostring-method) as well. And I'm sure there is a duplicate but I couldn't find it as always. – Soner Gönül Apr 07 '15 at 12:13
  • 2
    It's consistent with a lot of the [`Convert`](https://msdn.microsoft.com/en-us/library/System.Convert_methods(v=vs.110).aspx) methods (e.g. `ToBoolean(Boolean)`). It's worth remembering that the `Convert` class predates generics and wouldn't necessarily be the best way to build an API today. – Damien_The_Unbeliever Apr 07 '15 at 12:15
  • @SonerGönül: The [unary `+` operator](https://msdn.microsoft.com/en-us/library/k1a63xkz.aspx) might also be listed as another example of a seemingly useless declaration. – O. R. Mapper Apr 07 '15 at 12:16
  • In theory you could check to see if something were an `Int32` in your code somewhere. For example if you have the user input a number and your need it to be `Int32` you could run all inputs through a `Convert.ToInt32()` to make sure, I guess maybe? – 9Deuce Apr 07 '15 at 12:20
  • it's useful when dealing with generic T converts. if it's a `double` it use the `double`, if it's anything else than primitive it use the `object`, and if it's an `int32` it use the `int32`. if you override for object type only you wouldn't want an `int` to fall in that override. I have done that on a `Convert.ToDouble()` – Franck Apr 07 '15 at 12:26
  • Possibly because it would make things like `Convert.ChangeType` simplier. But as you say, you definitely don't want it using the object overload, so the choice may be between implementing this overload or producing an compiler error (which would probably be a lot more complicated). – sgmoore Apr 07 '15 at 12:28
  • 3
    maybe for reflection use? – Fredou Apr 07 '15 at 12:29
  • 4
    @SonerGönül No, `String.ToString` is very different since it is overridden virtual method. It simply is required for the runtime. – Georg Apr 07 '15 at 12:30
  • Maybe also to avoid unnecessary conversions? E.g. without it `int x = 3; int i = Convert.ToInt32(x);` would compile but needlessly call the `double` overload, generating a lot of instructions for basically a no-op. – CompuChip Apr 07 '15 at 12:31
  • @Georg Sure, I didn't said it is the _same_. – Soner Gönül Apr 07 '15 at 12:32
  • This is simply a fast path for 'bad' code. – leppie Apr 07 '15 at 12:36
  • There are other `Convert.To...`methods, that does not make any sense. For example `Convert.ToBoolean(DateTime)` - it throws always a `InvalidCastException`. https://msdn.microsoft.com/en-us/library/efbxsx53.aspx Therefore I think it does not exists an usefull answer for this question. – Koopakiller Apr 10 '15 at 01:29
  • What sort of details are you looking for? – Georg Apr 12 '15 at 09:51

5 Answers5

18

My ideas:

  • For code generation: Especially in .NET 2.0, a lot of code as e.g. typed data sets were generated. Having an overload like Convert.ToInt32(Int32) simplifies the code generator but does not hamper runtime performance, since the call is probably JITed away immediately
  • For consistency: There is an IConvertible interface in .NET since 2.0 or maybe even since 1.0 that is used by the Convert class. This interface demands methods like ToInt32, etc.

Code Generation (more details): The usual method to generate code back in .NET 2.0 times was System.CodeDOM as it provides means to reuse the same code generator for multiple languages, most prominently VB.NET and C#. In CodeDOM, you don't need to know of what type a given expression is to call a method, you can simply create a CodeMethodCallExpression given on the target object expression and the methods name. On the other hand, many cast operators such like C#s as operator are not supported by CodeDOM.

As a consequence, it is often hard to know the type of a given code expression in CodeDOM. This totally makes sense as many methods that an expression may involve are also part of the generated code and thus unknown at generation time. However, in some cases you need a particular expression converted to a given type, such as System.Int32. I can imagine this actually happened for typed data sets, although I am not 100% sure. Because Convert.ToInt32 exists, the generator does not need to know whether a given expression is of type System.Int32 or not. When the compiler compiles the generated code, all the methods signatures are available and the compiler may figure out that the type of the expression is System.Int32 and call the appropriate overload.

On the other side, the JIT compiler will detect that the method Convert.ToInt32 will simply return its argument. But as the method is not virtual, the methods body can be inserted into the callers code instead of calling Convert.ToInt32 as the overhead of calling the method would be much higher than the method body.

Georg
  • 5,626
  • 1
  • 23
  • 44
  • Interfaces don't apply to static members. – Theodoros Chatzigiannakis Apr 07 '15 at 12:29
  • @TheodorosChatzigiannakis Yes, I know, but basically the Convert class mirrors the signatures of the Convert class. – Georg Apr 07 '15 at 12:32
  • 1
    I think code generation is spot on. There used to be a lot of code generation in C#-of-that-time, especially before generics and expression trees. It also answers why you'd see `Convert.ToInt32` used instead of something more specific, like `int.Parse` or `(int)value` or whatever. – Luaan Apr 07 '15 at 12:38
5

Only the API designers know.

If I had to make a guess, I would guess it is for the sake of consistency - for example, when you are using reflection to dynamically create calls, it's easier if you can make the assumption that every Convert.ToX(Y) combination exists for any primitive types X and Y.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
1

We can derive one possible answer from usages of ToInt32(Int32) in the framework classes.

E.g. System.Activities.DurableInstancing.SerializationUtilities

public static byte[] CreateKeyBinaryBlob(List<CorrelationKey>correlationKeys)
{
     [...]
     Convert.ToInt32(correlationKey.BinaryData.Count)

and System.ComponentModel.Design.CollectionEditor

private void PaintArrow(Graphics g, Rectangle dropDownRect)
{
    Point point = new Point(Convert.ToInt32(dropDownRect.Left + dropDownRect.Width / 2), Convert.ToInt32(dropDownRect.Top + dropDownRect.Height / 2));

In both cases we can see that the type of the property or expression is currently Int32, but there's a reasonable expectation that /maybe/ that type might be different on different platforms, CPU architectures, future versions of the framework etc.

So my proposed answer is that it exists as a sort of future proofing of the source code, to allow it to compile without modification even when some key 'entities' (such as window X and Y coords) change type.

redcalx
  • 8,177
  • 4
  • 56
  • 105
  • +1 Say the reason was future proofing and a `Rectangle` with doubles was used in the *PaintArrow* method then you would expect a `Point` object supporting doubles to be used. The coder probably thought I'll force a Int32 `Point` object to be used even when instantiated with a Rectangle object supporting larger types. This way there wont be a mistake/misunderstanding why the common denominator is used **if/when** more accurate types are used, so its independent of graphics (or blob sizes). – Jeremy Thompson Apr 12 '15 at 06:10
0

Common Language Runtime use internally the IConvertible interface. As the CLR base types are Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char y String, there are an Implementation for each one of them in Convert class.

But, for example, Convert.toBoolean(DateTime) always return an Exception, by design.

Morcilla de Arroz
  • 2,104
  • 22
  • 29
0

Here's the method description:

    //
    // Summary:
    //     Returns the specified 32-bit signed integer; no actual conversion is performed.
    //
    // Parameters:
    //   value:
    //     The 32-bit signed integer to return.
    //
    // Returns:
    //     value is returned unchanged.

Only thing I can think of is that it's a shortcut/pass-through if the input is already an int. It's likely much more efficient than if an int was passed into Convert.ToInt32(object).

Jon Tirjan
  • 3,556
  • 2
  • 16
  • 24