1

I have a huge code base and I recently made a change where I changed the type of a parameter from String to a custom class. On the next compile I got all the areas where the impact was, but areas where the input type was of type Object failed. for e.g.

String str = "32"
int i = Convert.ToInt32(str)

Now I have changed String to a new custom type lets say MyCustomClass I would now want following code to fail on next compile

MyCustomClass str = new MyCustomClass("32")
int i = Convert.ToInt32(str)

but it won't as Convert.ToInt32 also accepts type Object. Is there some way I can make a change in MyCustomClass that it's not considered Object anymore. Please note: Convert.ToInt32 is only used for sample I have many more such functions, so please focus your suggestion/answer to question asked.

user961954
  • 3,214
  • 2
  • 17
  • 24
  • 3
    every type derives from object, you can't change that. the question is why you have methods that take object as parameter ? why not using type safe methods? or generics etc. ? – Selman Genç Mar 16 '17 at 17:40
  • nearly a duplicate question of http://stackoverflow.com/questions/436211/is-everything-in-net-an-object – hatchet - done with SOverflow Mar 16 '17 at 17:41
  • @KrikorAilanjian, Convert.ToInt32 is not his code. Can't refactor the base class libraries – Buh Buh Mar 16 '17 at 17:43
  • @KrikorAilanjian That's not possible as all of that code is third party or framework level. – user961954 Mar 16 '17 at 17:44
  • @BuhBuh my bad I misinterpreted what was being asked, I knew that `Convert.ToInt32` is not his code :) – Krikor Ailanjian Mar 16 '17 at 17:46
  • 3
    @user961954 Do you want to fail so you can fix all of the references, or do you actually want the int32 conversion to work? – johnny 5 Mar 16 '17 at 17:47
  • @johnny5 I just want it to fail so I can fix it. In any case it will fail in runtime but that will be too late as that would most likely be in production. I want to catch all of them in development. – user961954 Mar 16 '17 at 17:51
  • So you're end goal isn't really to find all the places where you need to change it, your end goal is to have a solution in which, Your Int32 Conversion won't fail – johnny 5 Mar 16 '17 at 17:56
  • @johnny5 my end goal is to find all the places where I need to change it. – user961954 Mar 16 '17 at 17:57
  • @user961954, so you're saying you would not accept a solution that fixed your problem with out having to change all of those references? – johnny 5 Mar 16 '17 at 17:58
  • @user961954 What do you intend to do with this line: `int i = Convert.ToInt32(str)`. Would you delete it? Replace it with `MyCustomClassConverter.ToInt32` ? – Buh Buh Mar 16 '17 at 18:01
  • @BuhBuh Once it fails during compile, I will know that I have to make a change here and I will let's say change it to `str.GetString()` where `str` is of type `MyCustomClass` – user961954 Mar 16 '17 at 18:03
  • 1
    Awesome, I think I have an answer. (half answer) – Buh Buh Mar 16 '17 at 18:05

3 Answers3

3

Override ToString() and IConvertible

You said in the comments that your intentions are to find places where your object, which had previously been treated as a string, and are now being treated as an object.

In these situations typically, the third-party code would call .ToString() on your object to get something which it can use.
So, Convert.ToInt32(str) is equivalent to Convert.ToInt32(str.ToString()).

If you implement ToString() and IConvertible to return whatever your old version of str looked like then it should continue to work in the same way as the old version.

Probably.

Sorry I know that is not the 100% perfect compile time answer you were looking for, but I think you also know very well that your MyCustomClass will always be considered object.

Buh Buh
  • 7,443
  • 1
  • 34
  • 61
  • [`Convert.ToInt32(object)`](https://referencesource.microsoft.com/#mscorlib/system/convert.cs,1024) calls `((IConvertible)value).ToInt32(null)` so you should implement `IConvertible` instead. – Lee Mar 16 '17 at 18:15
  • @Lee That kind of killed my flow. But ok great, thanks I've added that in! – Buh Buh Mar 16 '17 at 18:17
  • I think what I truly want is not achievable and as this comes closest to my solution I will accept this as answer. – user961954 Mar 16 '17 at 22:32
1

Possible compile time answer:

  • Write a tool which uses reflection to iterate over every class/struct/interface in every system/third-party DLL.

  • Output a load of CS files which contain all these same classes, but just throw NotImplementedException.
    (T4 could help you do this)

  • Compile these classes into dummy.dll

  • Your .csproj now references only this one dummy.dll, instead of the real dlls.
    Your project should compile fine against the dummy dll.

  • Look at your dummy.cs files and delete any use of object.

  • Re-compile... and suddenly you get a load of compile time errors showing you anywhere you are using an object.

Buh Buh
  • 7,443
  • 1
  • 34
  • 61
1

Impliment an implicit cast from MyCustomClass to String.

public static implicit operator string(MyCustomClass str)
{
    return "Legacy respresentation of str";
}

This allows the complier the choice of choosing ToInt32(Object) or ToInt32(String), and I bet it favours the later.

This way all your existing function calls will remain the same so you wont have to be concerned about third party implentation details.

(Sorry, I am not at a computer right now so I can`t test that my assumtion is correct. If you do test this, be sure to consider extension methods, as they can affect the conpilers desision making in unexpected ways)

Buh Buh
  • 7,443
  • 1
  • 34
  • 61