Lecture thumbnail 0:00 / 0:00 In this lesson, we’re going to take a look at yet another proxy type.

And this one is sufficiently different for us to dedicate a lesson to it because it’s not like the others.

In most cases.

When we were talking about proxies, we were talking about proxies over types which had lots of features,

lots of methods, different kinds of functionality.

Now a value proxy is a proxy that is typically constructed over a primitive type.

Now why would you want to construct a proxy over something like an INT or a float?

Well, there are many answers to this.

The most obvious answer is you want stronger typing.

So, for example, let’s suppose that you have some method.

Let’s suppose you have just some static method called foo which takes an integer x.

Now let us suppose that the integer that gets passed into foo can only represent, let’s say, the price

of an item in dollars.

How would you implement this?

Well, there is no way for us to explicitly say, Hey, this can only be a price because well, it’s

an int.

You can stick anything you want into an int, so you can certainly go ahead and specify the name of

the argument as being price.

But that doesn’t help much either because people can stick anything in here.

You could have a negative value, for example, that’s being stuck in here, even though maybe we don’t

allow negative values in the price.

So what do you do?

Well, one of the most obvious ways of dealing with this is building a value proxy.

Now, a value proxy is essentially just a wrapper around the primitive type, a primitive value, which

then provides a bunch of conversion operators to and from that value.

So you might have a public struct called price where you would have the value as a private member,

you would have some sort of constructor for actually initializing that member.

And then of course you would have the implicit conversion operators to price from INT and to int from

price.

Those are fairly obvious things.

Now with the price, what you would then do is you would simply specify price here and you are set,

you are getting an additional layer of safety in the sense that you know that people are not going to

stick anything in here, but maybe they will because if you define an implicit conversion operator from

an int to price, then they can still keep sticking ints in here.

So maybe this is something that you actually want to avoid.

So price is just a very simple example, but what we’re going to take a look at is a real world example

from something that I personally use, and that is the idea of storing a percentage value.

Now percentages are specific because they don’t just store a value, they also transform it.

When we talk about 50% of a hundred, for example, what do we mean by that?

Well, we don’t mean that we multiply 50 by 100.

We actually what we do is we first of all, convert the 50% into a multiplier.

So 50% is actually 0.5.

And so the first thing we do is we need to perform this conversion somewhere behind the scenes.

And only then can we actually apply this in, for example, multiplying it by some other value.

So let’s actually implement the percentage value proxy.

So it’s going to be a public struct called percentage.

And the first thing that we’re going to have here is we’re going to have the actual field for storing

the value.

So I’ll have private read only float value.

I’m choosing the single precision data type here, but you’re welcome to use either double precision

or in fact, what you can do is you can make this type generic, you can define a type T, and then

just just replace the float with T so that you can control whether you’re using floating point or double

values as the underlying.

I’m just going to stick with floating point single precision types for this particular example.

So let me show you what we actually want to build.

What do we actually want as the end result?

So here is the kind of things that we want to be able to calculate.

So we want, for example, to take the value ten and now take it as a float value and we want to multiply

it by 5%, something like this.

Or for example, what we want to do is we want to be able to add, let’s say, 2% and 3%.

So we want to be able to say something like 2% plus 3%, and we want to be able to actually have it

print not just 5 or 0.05.

We want it to print five and then the actual percentage symbol.

So how can we get all of this?

How can we get the correct operation?

Well, first of all, what you need to be able to do is you need to be able to invoke this on a literal.

And the only way you can do this is with extension methods.

So what I’m going to do is I’m going to build a static class called percentage extensions.

So percentage extensions is going to.

Allow us to construct a percentage class or a struct in this case from a value like an int.

So we’ll have something like public static percentage percent, so we’ll have percent from int value.

And all we have to do here is we take this value and remember this is the final multiplier, this is

the thing that we need to multiply.

So we take the value, we divide it by 100 and we return a new percentage with this value initialized

value divided by 100.0 F.

Now one thing you might notice here, which is a bit of a problem, is that the constructor to the percentage

happens to be public.

This isn’t a particularly good thing, and the reason why it’s not a good thing is because then you

need to explain to people what it means to be able to call this constructor.

What does it actually give you?

So one thing you can do, I suppose you could just change it to internal.

This does improve things somewhat, but on the other hand, you still have this, you still have this

issue that if people are working with this type inside the assembly, that where this type is defined,

they might call this constructor without really understanding what’s going on.

Anyways.

The idea of writing 5% is that the value 0.05 gets placed into value.

Now we also need a similar overload for integers because you can see that we still have an error here.

So writer is saying that you cannot apply well, you cannot apply the multiplication Operator But let

me show you something that’s also interesting.

If I were to change this to a float, then this would be invalid now.

And the reason it would be invalid is because five is an int and not a float.

It cannot be automatically converted or promoted to a float.

Therefore this will not work.

So essentially what I would do in this case is I would just create overloads so I would have an overload

for both float as well as INT and this covers all the cases.

Obviously we still have a problem that you cannot multiply a float value by a percentage value and this

is something that you can do using custom operators.

So here what you would do is you would define, for example, the multiplication operator, so you would

have something like public static float operator times where you take the float f as well as percentage

P and you simply return F multiply by P dot value.

There we go.

So this is how you would implement multiplication.

And notice now this line is okay because that’s exactly what we’re doing.

We’re multiplying a float by a percentage value.

Obviously if you were to spec out this class, if you were to implement all the necessary operators

here, you would have lots of operators.

Unfortunately, there is no way around this.

There is no way to define symmetric operations, meaning that if I multiply a percentage by a float,

I cannot say that this does the same thing just with the arguments reversed.

There is no way of doing it automatically.

So you would have to do a bit of work to implement this.

Now another thing that we want to do is we want to be able to add to percentage values.

Once again, this is something where you would have to define your own operators for all the binary

functions that you would support.

So, for example, in the case of percentages, that would be addition, multiplication, division and

subtraction, you can you probably don’t want to take a percentage to the power of a percentage or anything

like that, but you do want to be able to add them.

So here you would define a static percentage operator plus, and here you would take two percentage

values.

So a percentage A and percentage B, and what you would do here is fairly obvious really, because you

would just have to grab the make a new percentage.

So you would return a new percentage where you take the two values and add them together.

So a value plus B dot value.

And this hopefully covers the the last line in our example, this one where we add the two percentages

together.

So a few things that you might want to also implement as part of this class.

You might want to have two string implemented nicely showing the actual percent value.

So here if you add 2% and 3%, the internal value of the resulting percentage would be 0.05.

But you do want to show 5% and not 0.05.

So here, if I were to override two string, what I would probably put in here in the return value is

I would actually take the value and I would multiply it by 100 and then put the percentage sign after

it.

So this is how I would print that value.

You might also want to have a nice debugging display so you.

Would define debugger display to be something very similar.

So you would once again have value multiply by 100 and then put the put their percentage sign after

it.

In addition, you might want to define gethashcode and obviously the hashCode of this thing is the hash

code of the underlying.

In actual fact, what you can do is you can just use the use the code generation facilities.

So let’s see if I can find those.

I don’t have the insert key on my keyboard.

So you would generate.

No, not a constructor you would generate.

Let’s see, you would generate equality members.

That’s probably what you need.

So here you would use the value and you can overload all sorts of equality operations.

This puts in quite a bit more plumbing into your code and obviously get hash code here just uses the

hash code of the underlying value, which is completely correct.

This is the kind of behavior that you would actually want.

And so with all of this set up, what you have is a value proxy, which masquerades as a number, but

it’s really not.

It’s something that does its own behind the scenes kind of manipulations.

So I’m going to actually run this and we’ll take a look at what we get as we run both of these examples.

Hopefully we get the the right things.

So here when multiplying ten by 5%, you get 0.5.

And when taking 2% and 3% together, as you can see, we’re getting 5%.

So a value proxy is not a particularly common proxy.

But sometimes you really do want to wrap just a single primitive type, a primitive value with some

sort of additional plumbing, which in many cases doesn’t really do anything, and it just stores the

value and gives it a strongly typed wrapper, so to speak.

But in this case, you also perform additional operations and certainly the extension methods here provide

additional syntax sugar that we can use to construct out these value proxies on demand.

Play Play Play Stop Play Play Play Play Play Start Play Play information alert