C# Casting Nonsense

Introduction

I briefly mentioned the data types int (aka Int32) and long (aka Int64) in a previous blog Integer Overflow – Zaccaria Pinball. A key point is that the maximum value of an “Int32” type is 2,147,483,647, whereas “Int64” has a max of 9,223,372,036,854,775,807.

This blog is going to be more nerdy than my usual ramblings. It’s going to cover some C# code. In this blog, I’m going to show some interesting things that happen with Casting. Casting is defined by

A cast is a way of explicitly informing the compiler that you intend to make the conversion and that you are aware that data loss might occur, or the cast may fail at runtime.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions

Simple Casts

Casting is done by putting the datatype in brackets next to the variable. Let’s see that in action.

We can begin with an Int32 (I’ll call my variable “anInt32”). Then on the next line, I will cast it to an Int64.

 Int32 anInt32 = 50;
 Int64 anInt64 = (Int64)anInt32;

We can also start with an Int64 (I’ll call it “anInt64”). On the next line, I will cast to an Int32

 Int64 anInt64 = 50;
 Int32 anInt32 = (Int32)anInt64;

The number 50 can fit in either Int32 or Int64. This works just as I intended. Nothing bad happens. But let’s move onto the more interesting scenarios.

Downcasting – Dataloss

So let’s create a large number and correctly store it in a Int64. Then we try and down-cast it into an Int32. It’s isn’t going to fit, so what happens to the number?

Int64 largeInt64 = 19992244551234;
Int32 intNumber = (Int32)largeInt64;

It overflows. The number stored in the variable “intNumber” becomes -828211646 and we have a bug. This is basically what happened in the Zaccaria Pinball example. The number was simply too big to fit in the space that an Int32 allows. If you are playing a computer game, it’s better than out-right crashing, I guess.

Casting With Objects

The previous examples show you can convert between Int32 and Int64 by casting.

Instead of being very specific with your variables, you could declare variables as the base type “Object”. Despite Objects being set to a number type such as Int32 or Int64, you can only successfully cast when the type matches, otherwise it will give you a runtime error, and say the “System.InvalidCastException: Specified cast is not valid.“. It’s quite a hard thing to explain, but let’s see it in action.

We first declare a variable of type “Object”. It is implicitly an Int32. Then on the next line, we cast it to Int64. In previous examples this would be fine, but as I try to explain in the previous paragraph, declaring it as an Object seems to play by different rules. Therefore the following code throws the InvalidCastException, since the declaration was implicitly an Int32.

Object intObject = 30024;
Int64 int64cast = (Int64)intObject;

So if we declare it explicitly as an Int64, then casting from Object to Int64 does work because the underlying type was an Int64:

 Object int64Object = 30024L; //explicitly an Int64 by using the L character
 Int64 int64cast = (Int64)int64Object;

But, similarly, as we saw in the previous failed example, casting it to an Int32 results in InvalidCastException, because the type does not match.

 Object int64Object = 30024L; //explicitly an Int64 by using the L character
 Int32 intcast = (Int32)int64Object;

Very frustrating and quite confusing! Earlier in the blog, I was showing you that if the original types were declared as a proper number types (Int32 and Int64), we can cast between them. However, when it was originally declared simply as an Object, we can’t seem to do this.

Convert to the rescue

Instead of casting, we can use Convert. These examples work as intended.

Object intObject = 30024;
Int64 int64convert = Convert.ToInt64(intObject);

Object int64Object = 30024;
int intconvert = Convert.ToInt32(int64Object);

Try It Yourself

Here is the full code to easily paste into Visual Studio (or your favourite IDE) and try it yourself.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Playground
{
	class CastingNonsense
	{
		internal static void Run()
		{
			Test1();
			Test2();
			Test3();
			Test4();
			Test5();
			Test6();
			Test7();
		}

		private static void Test1()
		{
			Int32 anInt32 = 50;
			Int64 anInt64 = (Int64)anInt32;
			//fine
		}

		private static void Test2()
		{
			Int64 anInt64 = 50;
			Int32 anInt32 = (Int32)anInt64;
			//fine
		}

		private static void Test3()
		{
			Int64 largeInt64 = 19992244551234;
			Int32 intNumber = (Int32)largeInt64;
			//overflows, but doesn't crash. Number becomes -828211646
		}

		private static void Test4()
		{
			Object intObject = 30024;
			Int64 int64cast = (Int64)intObject; //InvalidCastException
		}

		private static void Test5()
		{
			Object int64Object = 30024L; //explicitly an Int64 by using the L character
			Int64 int64cast = (Int64)int64Object;
		}

		private static void Test6()
		{
			Object int64Object = 30024L; //explicitly an Int64 by using the L character
			Int32 intcast = (Int32)int64Object;
		}

		private static void Test7()
		{
			//Convert solves the problem of casting. This works fine
			Object intObject = 30024;
			Int64 int64convert = Convert.ToInt64(intObject);

			Object int64Object = 30024;
			int intconvert = Convert.ToInt32(int64Object);
		}
	}
}

Shelving, failed restart, then restarting a project

When we entered lockdown, there was a small project that was identified as urgent, and very helpful to our users due to the current situation. Originally, they estimated a simple change. So we make a change to one file. When testing it, we realise it didn’t send the information in the outbound messages to a third party. So we made further changes which were a few day’s work. 

We then had a meeting with a few different types of managers. They wanted to know about our progress and they wanted estimates to finish the project. I thought it would only take a few weeks to test. However the Tester said it would take 3 months which I think he was just being extreme to cover his back. He did explain it was more complex than I had thought, but still – it was clearly over exaggerated. The Managers didn’t like the idea of having a Tester tied up for that long, so the project went “on hold”.

Months later, I was invited to a meeting to restart the project. A Project Manager was ranting that there was a financial incentive to get the feature out by the end of the year (2020), but if we deliver it late, then we miss the bonus. Even if we restarted straight away, we had left it too late – there was no way the testing could get done, and deploy in time to meet such a deadline.

The Tester stressed that my solution is just a prototype and needs to be reworked. In reality, it was fine as far as I was aware, but he was just buying extra time if we needed it. It was the Testing side of things that needed the focus. We needed to test these extra configurations, but a prerequisite was that we needed to understand how they were set-up.

I couldn’t really do much work until the Tester had done this extra testing to see if my solution covers all the different configurations he had come up with. However, the Tester was busy with some other work so he couldn’t do that for a few weeks. A few weeks later, a Product Manager messages me to ask when the project started. I delivered the bad news: “It hasn’t”.

A few more weeks go by, and we have a meeting with a new Project Manager. So we discussed the story so far with him. It was also announced that the Tester (who has all the knowledge about this project) would only be partially available – so needs to pass on his knowledge to another Tester.

Another week or so goes by and another meeting was arranged. We have a new Project Manager.

Ridiculous.

She starts making all kinds of demands about having all the usual Agile process. (User Stories with estimates etc). However, it’s a weird project because we have basically done the development and we just need to test. All this process seemed a bit overkill to us.

We had another “Project Kick-Off” meeting, and the Tester asked the Software Architect about setting up all these different configurations. The Architect then said the Tester had misunderstood and there was actually only 1 configuration. 

This meant the testing time had been drastically slashed – you know; the exact reason why the project was delayed in the first place. So all these delays, extra meetings talking about the delay, all the meetings to rearrange the project; none of them actually needed to happen. We could have just completed the project when it was first assigned, additionally collecting that financial bonus.

numeronyms

When colleagues were talking about improving “accessibility” of our software, I saw them write “a11y” and wondered what crazy thing this was. It turns out it is a “numeronym” which is like an abbreviation, but really dumb.

What you do is keep the first and last letter, then any letter you remove between those, you count them, and put the number there instead. So there are 11 letters removed from the word “accessibility” so it becomes “a11y”. I also came across i18n (internationalisation), and K8s (Kubernetes).

This website has more information: https://a11yproject.com/posts/a11y-and-other-numeronyms/

I’d never really thought about what the W3 in “W3Schools” meant. Seems these stupid abbreviations have been around for years but haven’t really took off until recently.

A Day In The Life Of A Software Developer #1

At the start of the year, I thought of a new blog idea. I could pick certain days to give a run-down of the day’s work, including some banter. I drafted this up before the lock-down when we were working in the office. I hoped to write a few blogs in the series before posting them, but that didn’t work out. I suppose I could still write some based on working from home, but there won’t be as much banter to write about. So here it is. Note, this was when I was in a team doing a Web-based project:

I get into the office and give my previous day’s work a quick test before I send a Code Review to my team. I load up the website, open the menu… the menu is screwed up and won’t open at all.

I couldn’t understand what happened. I’m sure this was working yesterday. I spent some time analysing my changes; I really can’t see how this has happened.

The Junior Developer gets in and I ask him if he can give me any ideas on how this can happen. “Oh, I saw this happen yesterday.

What? You saw it, and never said anything? You didn’t log it, or even post it on Slack for the team to see?

No, it is a minor issue“.

I was outraged. I’ve told him not to ignore issues. We are paid to make things work. Also, if it was logged, I wouldn’t have wasted time analysing my changes when the bug isn’t even caused by my changes. If a bug is logged, if someone assigns it to themselves, then you know not to waste time looking at it, because it is being investigated. If the issue isn’t logged, you can end up with 2 team members looking into it because they think it’s a newly discovered problem.

We end up finding the cause, and we correct it.

Someone talks about a Pop music concert involving the groups: A1, Five, Damage and 911. “Sounds like a traffic report“, Seth says. We all laugh.

It’s time for the Scrum Of Scrums. Dean is currently occupying the meeting room on his own, but on a conference call. Helen waits outside and debates with a nearby colleague if she should kick him out of the room. Josh says “maybe Dean is waiting for the Scrum of Scrums?“. Helen says it wasn’t the case. Dean sees them awkwardly queuing outside, so he quickly leaves the room. The rest of the participants for the meeting show up. A minute later, Dean comes running back exclaiming “I should be in the meeting!“. I laugh at him.

A colleague tells me about a massive rant on Slack about the poor communication from management. I read it. It is brutal, but they make a good point. The upper management have kept quiet, when they used to hype up projects all the time. Additionally, new staff members have been quietly hired, some have even quietly left. We used to get emails to welcome the new starters, and also got emails to arrange leaving parties for departing staff.

Shortly after, some guy I have never seen before is asking a manager, Tim, about the progress of some important bug fixes. When he leaves, another manager asks “who the hell was that?” Tim replies “he has been here for 5 months, he is the latest Project Manager”.

Well, that certainly validates the Slack rant about the quiet hirings. No one in my team knew who he was either.

I’m happy with my work, so I send a Code Review to my team. I check to see if there’s any outstanding Code Reviews that I can review. Last week, I had left a comment about lack of test coverage. The developer hasn’t bothered adding any more tests. I ask him about it, he seems to be playing dumb. I told him I would sort it. So that is tomorrow’s work sorted.

First job – The “just Google it” seniors

When you are learning programming, I think it does help to have some kind of mentor, or alternatively – many mentors. There’s certain aspects that are hard to learn yourself. 

One simple example for me: Even though I could go out of my way to learn keyboard shortcuts, or find cool features of Visual Studio, I feel I have learnt the most by sitting next to someone while they work, or if they come over to help me. When they have the keyboard, they will bring up features I have never seen before, or manage to find files way faster than I could, and I’d be like “WOW! How did you do that?”. It’s amazing how much faster I am now, and it is mainly due to what I have learned from others.

When I started my first programming job, it was for a very small company (less than 10 staff), and I expected the Senior developers to help me a lot. Instead, when I asked them for help, they always said “just Google it”.

No matter how much I tried to argue with them that it would be faster for them to tell me, they would insist that I should Google it. If they were really busy, then fair enough, but I knew they didn’t have much work.

Sometimes you can find your answer fairly quickly by Googling. However, you still need to understand what you are reading, and sometimes it is far easier having someone explain it to you. It’s possible for someone to explain something in a few minutes, rather than reading a huge article for 20 minutes.

Also, you may not find your answer in the first article. You could have to trawl through several articles. Additionally, the articles could have a lot of irrelevant aspects to it that doesn’t apply to your situation, or confuse you further… possibly causing you to Google other terms you have seen on that article. You could end up with an hour passing by and you are left more confused than when you started.

Alternatively, maybe you find the correct answer, but the example code is in a different programming language.

Google only really works if you use the correct terms. If you know you have a problem but struggle to explain it, you don’t have much chance with Google, but an experienced human may be able to tell you the correct terms and concepts. At least a colleague has a good chance of understanding the problem you are trying to solve because they may have seen the requirements.

I vaguely remember spending ages trying to learn Threading, and I chose to use a “Thread” class. Then days later, when I had it working, I demoed it to the Seniors. They then said “why didn’t you use the Timer class, it is much easier?”

My thoughts were “why didn’t you tell me to use it when you knew exactly what I was working on, and knew I wanted some guidance?”.

It’s like they took great pleasure into watching Juniors struggle. They did mention that previous employees in my position left within 3 months, and they actually sounded quite proud of it. I always respect people that are smart and are willing to pass on their knowledge. It’s frustrating when you meet people that are smart but are so arrogant and patronising about it.

Bad Quality Project

Recap

The Code Analysis report gives metrics on code quality, and we want to improve the overall quality of our code over time. We put great importance on the Code Analysis report even though we haven’t done anything to address the issues. It’s just that certain managers keep hyping up how important it is.

New Project

An important project is going into the Main branch which will be released next month. I was asked to review the code. I was originally told the review would be sent by the end of the day, but it was delayed a day. I proactively found their code branch and saw it was out of date by a few months, which isn’t a good sign. (They should be merging Main into their project branch to minimise code conflicts).

So after they finally updated it to the latest version and sent the review, a manager said they “really need to get the project reviewed and approved by 5pm so they can start the regression testing tomorrow”. 

I jestingly asked if the expectation is that ‘I click the “Approve” button without looking at the code’ – if I criticised their code in any way, then they would miss the deadline since they would have to make the changes and retest those features. It was true though, the deadline was about 3 hours time.

Since we are more ethical than that, a few of us ripped it apart. Initially, we ended up with around 100 comments which I think is the largest I’ve seen on a review. The next day, we added even more to get it up to around 130.

If they really wanted to cut corners, then it’s up to the managers to decide whether they want to skip the review and check it in anyway.

I thought the pressure they were putting on the reviewers was unfair. It wasn’t just that initial message (“need to get the project reviewed and approved by 5pm”), but they kept on sending direct messages to each of us asking when we will be finished because we are pushing time.

Code Critique

Instead of moving some old code to a new location, and refactoring it so it is reusable with the new features (utilising C#’s object-oriented style (base and derived classes), then fixing up the existing issues to meet our coding standards)… they decided to copy and paste it instead.

So now we have some old, bad code; and some new, bad code. When the Code Analysis report runs, it is going to flag up issues in both files, and if it successfully identifies the duplication, we will have loads of Code Duplication errors too. Brilliant.

I expressed my concern to the team’s manager and he gave me a response along the lines of “we were a bit pushed for time, so decided to take the easy route”.

On the review, I questioned some of the messages we were displaying to the user, and the response I got was “this is an existing message”. Well, fair enough to a point, but why didn’t anyone question if it should be changed. You are revamping that area of the system, why don’t you improve the quality and user experience whilst you are there? The project has enough testers allocated to it, and they will be testing these changes in detail. It’s a great opportunity to rewrite it.

There were several files where their response was “actually, this file isn’t used, so I’m deleting it”. I’m not sure how that can happen with several files. Why only realise now?

Closing Thoughts

After all those discussions about how our team is supposed to have Quality as our main focus, then we proceed to make a mess of things!

It would be nice to have some consistency. If I check in some code that shows up on the report, then I get an email from someone. It doesn’t matter if I have reduced the problem count by 50, but added 1 new problem – they make out it is a problem. 

Why is someone manually emailing about what a report shows, rather than having it as an automated check as part of the review? Maybe it’s a licencing issue. If they were that serious about this report then they would pay for it and enforce it properly.

There’s been a few times where projects were supposed to be merged in, and the people doing the code review didn’t like the code. If you are doing a project, maybe get an expert to review your code earlier in the project. That way, you don’t get loads of issues to fix on the day you are supposed to merge it.

Dumb Code List

There was one code review I was having a nosey at, and the Lead Developer tore it apart. It had so many mistakes in it, I thought I’d make a note of the best ones.

  1. string.IsNullOrEmpty(null)

We are passing “null” into a method and asking “is this null”? Yes it is. 100% guaranteed to be.

  1. new FilingContainer(fEvent) ?? new FilingContainer(fEvent, null); 

This code means: “create a new FilingContainer. If this is null, then create a new FilingContainer (but with slightly different parameters”

Lead Developer’s comment: “how does this constructor return null?”

A constructor can only return a new object, or throw an exception. You can never return a “null” value. So the second part of the statement would never execute.

  1. There was a massive constructor defined with many parameters of the same type. So like

public  Ticket(
String firstName,
String secondName,
Int userId,
String userName
,
Int jobCategoryId,
String jobCategoryName
)

But then when he went to use it, he had the parameters in the wrong order:

new Ticket(
firstName,
secondName,
jobCategoryId,
jobCategoryName
,
userId,
userName)

Lead Developer’s comment: “You are setting the JobCategoryId to something called UserId! Which is a hard coded value from your development database, and cannot be relied on to be the same in Live! You are setting the JobCategoryName to the User’s Name!”

So not only were the parameters in the wrong order, he should have queried the database for the correct JobCategoryId in his code. But he had queried it manually, then hardcoded the value in his code, so it would only work on his machine.

  1. Title + surname.toTitleCase( ) + “ ?” + firstname;

Lead Developer’s comment: this is “MrSmith ?DAVE” Also, is title-case correct? What if someone’s name is McDonald? Should it be Mcdonald?

Pretty much everything is wrong with the output!

  1. Lead Developer’s comment: “Sex or gender, use one or the other”.

Some files they had named a variable “sex” and in others “gender”. Obviously, only one name is correct.

  1. Age = (DateTime.Today.Year - messageDetails.User.DateOfBirth.Year).ToString());

Lead Developer’s comment: “Born 31/12/2000 Today 1/1/2001… does not make you 1!”

I’m not sure what sort of people think age is a calculation based on year only, but with that lack of attention, you really need to consider if this is the job for you. Programming is about thinking logically.

  1. FullName = Title + Surname; 

Lead Developer’s comment: FullName is just “MrSmith” (nospaces) is that correct? 

They reply “yes there will be no space”

Is that really in the requirements? I highly doubt it. Are they that stupid that they think the Lead Developer is asking how their code currently behaves, rather than questioning if the behaviour is actually correct?

  1. There was a variable named “refferalDescription”. Which is an incorrect spelling.

Lead Developer’s comment: “referralDescription?” 

They reply “refferalDescription is new property for code which is used to display in the referral document.” 

I was thinking “How can you write that response and not realise that the spelling is different in his comment to what you wrote?”

  1. Referral.Code ?? null. 

This code means, If it is null, then use null. A completely redundant line of code.

Missing Feature

Cassie: Can I ask you a question?

Me: What is it?

Cassie: A user has complained that a feature has been removed in version 7.5, can you check why? I’ve recreated it on my system.

I check on my system and the feature is there. I look at the code and it is specifically for users in England.

Me:  Is the Region of the organisation set to England?

Cassie: It will be, also I’ve recreated the issue on a second system which is set to Scotland

Me: Yes, this is an England only feature

Cassie: Ah, doesn’t explain why it doesn’t show on the other test system though

Me: Can you check the region?

Cassie: It is Wales

Me: This doesn’t explain why the user doesn’t have the feature though.

Cassie: They are in Scotland

Now I’d like to know if the user has really complained that a feature has been removed. They should never have had it in the first place. I think there has been some miscommunication here, and the user has probably read about the feature and questioned why they don’t have it.