What are Widening and Narrowing conversions?

Asked

Viewed 79 times

3

I’ve heard that term in type conversions on . NET, but I don’t know if that applies to other platforms and/or languages.

I have no idea what these terms are, so what is a conversion Narrowing and a Widening? What are your differences and where do I use them?

  • 1

    I believe you’ve read this before: Widening and Narrowing Conversions (Visual Basic) . But it is very technical and difficult to understand. .

  • 2

    @Luizaugusto I came to read there, but for the same reason I did not have a good understanding in the difference between the two. In fact, I don’t even understand what they are.

1 answer

5


Widening

It is to take a value and treat it as something broader, that is, you take a value that has a smaller magnitude and put in a type that allows a greater magnitude, so there will never be data loss. Some people think that there is always a conversion in these cases, but this is not true, it exists in some cases, but not at all. The important thing is that it is safe to do this kind of operation.

It is not complicated to understand, if you have a number that is stored in 2 bytes, and you have a memory location that is prepared to accommodate a number that takes 4 bytes, it puts the 2 bytes there and completes the other 2 bytes with non-significant zeros in the other bytes so as not to misrepresent the value (the exact location depends on the architecture, but you don’t have to worry about it). Something like that (exemplifying with decimal to visualize better, but in memory it’s all binary) think you have room for 8 digits somewhere, the original number only has 4:

1234
00001234

A very common example is to put a value int in a variable or slot in expression that awaits a long, this value shall be treated as a long normally smoothly.

It is common for languages to allow this to be done implicitly (some do not). But it does not mean that there are never problems, there is no loss, but it can generate unexpected results in some more specific situations, for example when it changes float for double or decimal for double since these guys have accuracy problems. In addition to some cases the operation of widening can generate overflow in others that could not.

Narrowing

It is the opposite, so it is trying to put a value of greater magnitude where only one of lesser magnitude fits. Obviously in many cases there will be loss of data, either accuracy or accuracy, in some cases with great differences, since there is no space to store all the necessary information. There are cases that the value can be accommodated in the smaller type without major problems. It also doesn’t mean there is a conversion, but without a conversion the chance of error is greater.

Here it is more complicated to understand a little so I will try to use the previous example to show what happens. Now you have the original number with the same 4 digits, but you only have room for 2 of them in memory, which happens?

1234
12

You noticed the loss, right? It’s terrible, the value has no meaning. A typical example is to try to put a value int in a kind short that has half the size in memory and therefore can represent values much smaller than the intcan.

Another example that people do not realize and so the use is dangerous is trying to put an unmarked value (unsigned) in a flagged type, although they have the same amount of bits one of these bits is used for the signal so the maximum value it allows is less, has cases of a loop becoming infinite because of this, since the value grows until an hour it "out of nowhere" becomes negative, and then never reaches the condition that would end it and you didn’t even see the value change. This is one of the motifs we talk about to avoid unsigned to the maximum.

It is also common for an arithmetic operation to create a value that bursts the type normally used and an Narrow can happen implicitly, for example: multiply 1 billion by 1000 does not fit in an integer although originally 1 billion fit and if everything was waiting to use was a int some loss may occur because there was a widening implicit in multiplication and then there was a narrowing to fit into the space it originally had.

No completely sane language should let you do this implicitly (but almost all leave one way or another, some change the number representation to fit anyway, but not on the .NET). It is complicated for languages to prevent under all circumstances and would leave everything very inefficient, C# has as link this in some circumstances (does not solve all problems). Even explicitly you need to be careful because there might be loss if you’re not sure what you’re doing, something like that: (short)1234. But there are cases that have no problem, example here occurs the narrowing from 8 digits to 4 and has no loss:

00001234
1234

Of course, the subject is more complex, involving other types that allow their values to be interpreted as other types with or without loss because the destination type is more or less broad, but the basis is this.

Hierarchy

This can happen with hierarchy. If an object derives from another object it is common for it to have new fields that the derivative did not have (not so common, but reasonably), if you try to place the derivative type in a location that was waiting for the base type does not fit then something will be lost. It may not cause a major problem at the time because your code will not be able to access anything of the derivative type even, but if you later try to take this object as the derivative type the derivative specific data will not be there. This is called slicing.

Luckily for him. NET doesn’t let you do this, as it could only do something like this in types by reference so it always has room for the whole derivative type to be in memory (thank you indirect) and types by value have no inheritance so there is no way this phenomenon happens (in C/C++ can). That’s why I couldn’t give you any more details.

Then it gets confused because when you convert from a derivative type to a database has loss, even if not of data, but of behaviors (some methods that exist in the derivative type may not exist in the base type, very common), calls it widening since the type is more general.

And when it converts the base type to a derivative type it’s called narrowing since he happens to be a more specific type, but this is a case that he gains capacity instead of losing.

But I understand that the motivation is why widening always works (at least if you pass the compilation), after all the original type is always compatible with its base, and the opposite does not always work since the object needs to be compatible and it may not be, so it needs to be explicit, so they called it narrowing, is consistent in this regard.

I think in these cases you should just call upcasting and downcasting respectively.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.