I'm new to C#, and I want to use a track-bar to change a form's opacity.

This is my code:

decimal trans = trackBar1.Value / 5000
this.Opacity = trans

When I try to build it, I get this error:

Cannot implicitly convert type 'decimal' to 'double'

I tried making trans a double, but then the control doesn't work. This code worked fine for me in VB.NET.

What do I need to do differently?

+59  A: 

An explicit cast to double isn't necessary.

double trans = (double)trackBar1.Value / 5000.0;

Identifying the constant as 5000.0 (or as 5000d) is sufficient:

double trans = trackBar1.Value / 5000.0;
double trans = trackBar1.Value / 5000d;
Kevin Dente
+2  A: 


I thought the modifier for decimal on the numbers was "m" as in the only Money datatype. And "d" was used for Double datatype.

@jeff, @kevin

I thought that the use of 5000.0 actually is compiled as a double?

It has been a while since I have looked at the trackbar. My assumption is that the .Value is return a decimal, if I am wrong please ignore.

Nick Berardi

It sounds like this.Opacity is a double value, and the compiler doesn't like you trying to cram a decimal value into it.

Ryan Fox
+18  A: 

A more generic answer for the generic question "Decimal vs Double?": Decimal for monetary calculations to preserve the precision, Double for scientific calculations that do not get affected by small differences. Since Double is a type which is native to the CPU (internal representation is stored in base 2), calculations made with Double perform better then Decimal (which is represented in base 10 internally).

+2  A: 

In addition (or instead) of adding a .0 to the number, in my opinion it is also desirable to be as explicit as possible, for understandability and aid to your fellow programmers that eventually will read your code =).

Using decimal.ToDouble(), like so:

double transperancy = trackBar1.Value/5000;
this.Opacity = decimal.ToDouble(transperancy);

or, even

this.Opacity = decimal.ToDouble(trackBar1.Value/5000);
Andreas H.R. Nilsson
+1  A: 

@Nick: trackBar1.Value is actually of type int.

So that explains why dividing by a double actually works. When I first looked at the code, I thought Value was a string...

+10  A: 

Your code worked fine in VB.NET because it implicitly does any casts, while C# has both implicit and explicit ones.

In C# the conversion from decimal to double is explicit as you lose accuracy. For instance 1.1 can't be accurately expressed as a double, but can as a decimal (see "Floating point numbers - more inaccurate than you think" for the reason why).

In VB the conversion was added for you by the compiler:

decimal trans = trackBar1.Value / 5000m;
this.Opacity = (double) trans;

That (double) has to be explicitly stated in C#, but can be implied by VB's more 'forgiving' compiler.

+8  A: 

Why are you dividing by 5000? Just set the TrackBar's Minimum and Maximum values between 0 and 100 and then divide the Value by 100 for the Opacity percentage. Minimum 20 example below prevents the form from becoming completely invisible.

private void Form1_Load(object sender, System.EventArgs e)
    TrackBar1.Minimum = 20;
    TrackBar1.Maximum = 100;

    TrackBar1.LargeChange = 10;
    TrackBar1.SmallChange = 1;
    TrackBar1.TickFrequency = 5;

private void TrackBar1_Scroll(object sender, System.EventArgs e)
    this.Opacity = TrackBar1.Value / 100;
Gordon Bell

Also, Decimal can't represent as wide a value as a Double.

Decimal can only go up to +/-7.9228162514264337593543950335E+28; whereas a Double can go up to +/-1.79769313486232E+308


Use 5000.0 instead of 5000

+3  A: 

You have two problems. First, Opacity requires a double, not a decimal value. The compiler is telling you that while there is a conversion between decimal and double, it is an explicit conversion that you need to specify in order for it to work. The second is that TrackBar.Value is an integer value and dividing an int by an int results in an int, no matter what type of variable you assign it to. In this case there is an implicit cast from int to decimal or double -- because there is no loss of precision when you do the cast -- so the compiler doesn't complain, but the value you get is always 0, presumably, since trackBar.Value is always less than 5000. The solution is to change your code to use double (the native type for Opacity) and do floating point arithmetic by explicitly making the constant a double -- which will have the effect of promoting the arithmetic -- or casting trackBar.Value to double, which will do the same thing -- or both. Oh, and you don't need the intermediate variable unless it used elsewhere. My guess is the compiler would optimize it away, anyway.

 trackBar.Opacity = (double)trackBar.Value / 5000.0;

Decimal can only go up to +/-7.9228162514264337593543950335E+28; whereas a Double can go up to +/-1.79769313486232E+308

Acacio Nerull