Equivalent implicit operators: why are they legal? - c#

Update!
See my dissection of a portion of the C# spec below; I think I must be missing something, because to me it looks like the behavior I'm describing in this question actually violates the spec.
Update 2!
OK, upon further reflection, and based on some comments, I think I now understand what's going on. The words "source type" in the spec refer to the type being converted from -- i.e., Type2 in my example below -- which simply means that the compiler is able to narrow the candidates down to the two operators defined (since Type2 is the source type for both). However, it cannot narrow the choices any further. So the key words in the spec (as it applies to this question) are "source type", which I previously misinterpreted (I think) to mean "declaring type."
Original Question
Say I have these types defined:
class Type0
{
public string Value { get; private set; }
public Type0(string value)
{
Value = value;
}
}
class Type1 : Type0
{
public Type1(string value) : base(value) { }
public static implicit operator Type1(Type2 other)
{
return new Type1("Converted using Type1's operator.");
}
}
class Type2 : Type0
{
public Type2(string value) : base(value) { }
public static implicit operator Type1(Type2 other)
{
return new Type1("Converted using Type2's operator.");
}
}
Then say I do this:
Type2 t2 = new Type2("B");
Type1 t1 = t2;
Obviously this is ambiguous, as it is not clear which implicit operator should be used. My question is -- since I cannot see any way to resolve this ambiguity (it isn't like I can perform some explicit cast to clarify which version I want), and yet the class definitions above do compile -- why would the compiler allow those matching implicit operators at all?
Dissection
OK, I'm going to step through the excerpt of the C# spec quoted by Hans Passant in an attempt to make sense of this.
Find the set of types, D, from which
user-defined conversion operators will
be considered. This set consists of S
(if S is a class or struct), the base
classes of S (if S is a class), and T
(if T is a class or struct).
We're converting from Type2 (S) to Type1 (T). So it seems that here D would include all three types in the example: Type0 (because it is a base class of S), Type1 (T) and Type2 (S).
Find the set of applicable
user-defined conversion operators, U.
This set consists of the user-defined
implicit conversion operators declared
by the classes or structs in D that
convert from a type encompassing S to
a type encompassed by T. If U is
empty, the conversion is undefined and
a compile-time error occurs.
All right, we've got two operators satisfying these conditions. The version declared in Type1 meets the requirements because Type1 is in D and it converts from Type2 (which obviously encompasses S) to Type1 (which is obviously encompassed by T). The version in Type2 also meets the requirements for exactly the same reasons. So U includes both of these operators.
Lastly, with respect to finding the most specific "source type" SX of the operators in U:
If any of the operators in U convert from S, then SX is S.
Now, both operators in U convert from S -- so this tells me that SX is S.
Doesn't this mean that the Type2 version should be used?
But wait! I'm confused!
Couldn't I have only defined Type1's version of the operator, in which case, the only remaining candidate would be Type1's version, and yet according to the spec SX would be Type2? This seems like a possible scenario in which the spec mandates something impossible (namely, that the conversion declared in Type2 should be used when in fact it does not exist).

Ultimately, it can't be prohibitted with complete success. You and I could publish two assemblies. They we could start using each other's assembles, while updating our own. Then we could each provide implicit casts between types defined in each assembly. Only when we release the next version, could this be caught, rather than at compile time.
There's an advantage in not trying to ban things that can't be banned, as it makes for clarity and consistency (and there's a lesson for legislators in that).

We don't really want it to be a compile-time error just to define conversions which might cause ambiguity. Suppose that we alter Type0 to store a double, and for some reason we want to provide separate conversions to signed integer and unsigned integer.
class Type0
{
public double Value { get; private set; }
public Type0(double value)
{
Value = value;
}
public static implicit operator Int32(Type0 other)
{
return (Int32)other.Value;
}
public static implicit operator UInt32(Type0 other)
{
return (UInt32)Math.Abs(other.Value);
}
}
This compiles fine, and I can use use both conversions with
Type0 t = new Type0(0.9);
int i = t;
UInt32 u = t;
However, it's a compile error to try float f = t because either of the implicit conversions could be used to get to an integer type which can then be converted to float.
We only want the compiler to complain about these more complex ambiguities when they're actually used, since we'd like the Type0 above to compile. For consistency, the simpler ambiguity should also cause an error at the point you use it rather than when you define it.
EDIT
Since Hans removed his answer which quoted the spec, here's a quick run through the part of the C# spec that determines whether a conversion is ambiguous, having defined U to be the set of all the conversions which could possibly do the job:
Find the most specific source type, SX, of the operators in U:
If any of the operators in U convert from S, then SX is S.
Otherwise, SX is the most encompassed type in the combined set of target types of the operators in U. If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
Paraphrased, we prefer a conversion which converts directly from S, otherwise we prefer the type which is "easiest" to convert S to. In both examples, we have two conversions from S available. If there were no conversions from Type2, we'd prefer a conversion from Type0 over one from object. If no one type is obviously the better choice to convert from, we fail here.
Find the most specific target type, TX, of the operators in U:
If any of the operators in U convert to T, then TX is T.
Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. If no most encompassing type can be found, then the conversion is ambiguous and a compile-time error occurs.
Again, we'd prefer to convert directly to T, but we'll settle for the type that's "easiest" to convert to T. In Dan's example, we have two conversions to T available. In my example, the possible targets are Int32 and UInt32, and neither is a better match than the other, so this is where the conversion fails. The compiler has no way to know whether float f = t means float f = (float)(Int32)t or float f = (float)(UInt32)t.
If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator. If no such operator exists, or if more than one such operator exists, then the conversion is ambiguous and a compile-time error occurs.
In Dan's example, we fail here because we have two conversions left from SX to TX. We could have no conversions from SX to TX if we chose different conversions when deciding SX and TX. For example, if we had a Type1a derived from Type1, then we might have conversions from Type2 to Type1a and from Type0 to Type1 These would still give us SX=Type2 and TX=Type1, but we don't actually have any conversion from Type2 to Type1. This is OK, because this really is ambiguous. The compiler doesn't know whether to convert Type2 to Type1a and then cast to Type1, or cast to Type0 first so that it can use that conversion to Type1.

Related

Console.WriteLine(Enum.Value) gives different output in C# and VB.Net

I am basically a C# guy, but writing VB.Net code these days.
Today I came across a very different behaviour of .Net
C# Code
enum Color
{
Red,
Green,
Blue
}
class Demo
{
public static void Main()
{
System.Console.WriteLine(Color.Red);
}
}
This prints Red
But when this code is written in VB.Net it prints 0.
VB.Net Code
Module Module1
Sub Main()
System.Console.WriteLine(Color.Red)
End Sub
End Module
Enum Color
Red
Green
Blue
End Enum
Why so different?
There is no Console.WriteLine(Enum) overload so the compilers are forced to pick one of the other ones. Overload resolution rules are very arcane and the VB.NET and C# rules are not the same, but both compilers are willing to pick one when there's an implicit conversion to the target argument type and pick the one that takes the least amount of work.
Which is where another rule applies, this kind of statement in VB.NET is perfectly valid:
Dim example As Integer = Color.Red '' Fine
But the C# compiler spits at:
int example = Color.Red; // CS0266
Insisting that you apply an (int) cast. It only has an explicit conversion, not an implicit one like VB.NET.
So the C# compiler is going to ignore all the overloads that take an integral argument, none are candidates because only explicit conversions exist for them. Except one, the Console.WriteLine(Object) overload. There is an implicit conversion for that one, it takes a boxing conversion.
The VB.NET compiler sees it as well, but now the "better" conversion comes into play. A boxing conversion is a very expensive conversion, converting to Integer is very cheap. It requires no extra code. So it likes that one better.
Workarounds are simple:
System.Console.WriteLine(CObj(Color.Red)) '' or
System.Console.WriteLine(Color.Red.ToString())
C# and VB.NET have different method overload resolution rules.
C# Picks Console.WriteLine(Object), while VB.NET picks Console.WriteLine(Int32). Let's see why it does so.
VB.NET rules:
Accessibility. It eliminates any overload with an access level that prevents the calling code from calling it.
Number of Parameters. It eliminates any overload that defines a different number of parameters than are supplied in the call.
Parameter Data Types. The compiler gives instance methods preference over extension methods. If any instance method is found that requires only widening conversions to match the procedure call, all extension methods are dropped and the compiler continues with only the instance method candidates. If no such instance method is found, it continues with both instance and extension methods.
In this step, it eliminates any overload for which the data types of the calling arguments cannot be converted to the parameter types defined in the overload.
Narrowing Conversions. It eliminates any overload that requires a narrowing conversion from the calling argument types to the defined parameter types. This is true whether the type checking switch (Option Strict Statement) is On or Off.
Least Widening. The compiler considers the remaining overloads in pairs. For each pair, it compares the data types of the defined parameters. If the types in one of the overloads all widen to the corresponding types in the other, the compiler eliminates the latter. That is, it retains the overload that requires the least amount of widening.
Single Candidate. It continues considering overloads in pairs until only one overload remains, and it resolves the call to that overload. If the compiler cannot reduce the overloads to a single candidate, it generates an error.
There are a lot of overloads for WriteLine, some of them are discarded at step 3. We're basically left with the following possibilities: Object and the numeric types.
The 5th point is interesting here: Least Widening. So what do the widening rules say?
Any enumerated type (Enum) widens to its underlying integral type and any type to which the underlying type widens.
Any type widens to Object
So, your Color enum first widens to Int32 (its underlying data type) - and this is a 100% match for Console.WriteLine(Int32). It would require yet another widening conversion to go from Int32 to Object, but the rules above say to retain the overload that requires the least amount of widening.
As for C# (from the C# 5 spec at §7.5.3.2):
Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN }, MP is defined to be a better function member than MQ if
for each argument, the implicit conversion from EX to QX is not better than the implicit conversion from EX to PX, and
for at least one argument, the conversion from EX to PX is better than the conversion from EX to QX.
Ok, now how is better defined (§7.5.3.4)?
Given a conversion C1 that converts from a type S to a type T1, and a conversion C2 that converts from a type S to a type T2, C1 is a better conversion than C2 if at least one of the following holds:
An identity conversion exists from S to T1 but not from S to T2
T1 is a better conversion target than T2 (§7.5.3.5)
Let's see at §7.5.3.5:
Given two different types T1 and T2, T1 is a better conversion target than T2 if at least one of the following holds:
An implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists
T1 is a signed integral type and T2 is an unsigned integral type.
So, we're converting from Color to either Object or Int32. Which one is better according to these rules?
There is an implicit conversion from Color to Object
There is no implicit conversion from Object to Color (obviously)
There is no implicit conversion from Color to Int32 (these are explicit in C#)
There is no implicit conversion from Int32 to Color (except for 0)
Spec §6.1:
The following conversions are classified as implicit conversions:
Identity conversions
Implicit numeric conversions
Implicit enumeration conversions.
Implicit nullable conversions
Null literal conversions
Implicit reference conversions
Boxing conversions
Implicit dynamic conversions
Implicit constant expression conversions
User-defined implicit conversions
Anonymous function conversions
Method group conversions
Implicit numeric conversions make no mention of enum types, and Implicit enumeration conversions deal with the other way around:
An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type and to any nullable-type whose underlying type is an enum-type. In the latter case the conversion is evaluated by converting to the underlying enum-type and wrapping the result (§4.1.10).
Enums are handled by boxing conversions (§6.1.7):
A boxing conversion permits a value-type to be implicitly converted to a reference type. A boxing conversion exists from any non-nullable-value-type to object and dynamic, to System.ValueType and to any interface-type implemented by the non-nullable-value-type. Furthermore an enum-type can be converted to the type System.Enum.

Implicit cast of Func<MyType> to MyType

Given the following class:
public class MyType
{
public static implicit operator MyType(Func<MyType> wrapper) {
return wrapper();
}
}
From the implicit cast of Func<MyType> to MyType, I assumed the following would be possible:
public MyType MyTypeWrapper() {
return new MyType();
}
public void MyTestMethod() {
MyType m = MyTypeWrapper; // not a call!
}
However I'm getting:
Cannot convert method group 'MyTypeWrapper' to non-delegate type 'Test.MyType'. Did you intend to invoke the method?
Which, unfortunately for me, when searched for (as I half expected) resulted in tons of questions to which the answer was:
Hey, ya dun goofed; toss () on the end of WhateverMethod!
Now, as I'm typing this, I've noticed that an explicit cast does in fact compile:
MyType m = (MyType) MyTypeWrapper;
Why is it that I cannot implicitly cast a Func<MyType> to MyType as I've described?
This is unfortunate. I'm pretty sure you've found a compiler bug, and this section of the specification is extremely difficult to read.
Section 6.4.4 of the C# 4 specification explains why your implicit conversion is illegal.
The algorithm goes like this. First look at the source type and target type. There is no source type because a method group has no type. The target type is MyType. So search MyType for user-defined implicit conversions. Now the question is: what is the set of applicable user-defined operators ... that convert from a type encompassing S? S is the source type and we have already established that there is no source type. So this is already evidence that the conversion should fail. But even if the compiler for some reason decides that your Func<MyType> conversion is applicable, the rule is a standard implicit conversion ... is performed. Method group conversions are deliberately not classified as standard conversions.
So that's why it should be illegal.
Why then is the explicit cast legal?
There's no justification for that. This appears to be a bug.
This is unfortunate; many apologies for the error. I shall report it to my former colleagues; if they have an analysis which conflicts with mine, I'll update the answer.
UPDATE: My former colleagues inform me that the spec problem whereby the source expression is assumed to have a type will be addressed by a rewording in the next release of the spec. No word yet as to whether the explicit cast behavior is a bug.
You're already using the built-in implicit conversion from method group to Func<MyType>.
The compiler won't do two implicit conversions at once.
Once you have an explicit cast to your class, the compiler knows to look for an implicit cast to any type that can be explicitly casted to your class.
Because the C# compiler isn't able to convert MyTypeWrapper into a Func<MyType>(MyTypeWrapper). There's a difference between a method group and an actual delegate.
This compiles and runs fine:
MyType m = new Func<MyType>(MyTypeWrapper);
There is an implicit conversion from a method group to a delegate type that matches that group, and there is your user defined implicit conversion from that delegate to a type. The general idea here is that the compiler is only going to use one implicit conversion in a row at a time. When it has an A and needs a C it looks for conversions from A to C, not from A to any type B and from that type to C. That algorithm goes from O(n) to O(n^2) (not to mention possibly being quite confusing for programmers).
The reason your code works when using an explicit cast to MyType is that you're no longer chaining implicit conversions.
The signature of MyTestMethod MATCHES the signature of Func<MyType> but is NOT a Func<MyType>. Func has defined some implicit casts itself to allow you to assign such methods as Funcs, but you must explicitly cast for the signature to apply, because the compiler will not chain implicit casts together for you:
MyType m = (Func<MyType>)MyTypeWrapper; // not a call!

Multiple system explicit converters are allowed, but mutiple user explicit converters are not. Why?

If I have this code, this will compile and work as it should:
class MyNumber // Just a class.
{
static public explicit operator MyNumber(byte b)
{
return new MyNumber();
}
}
Decimal d = new Decimal();
MyNumber c1 = (MyNumber)d;
Perhapse some people are a bit of a surprise, since there is no existing explicit cast from a decimal to MyNumber. But since there is a explicit cast from decimal to byte and there is also a explicit cast from a byte to MyNumber, the compiler is kind enough to insert that extra explicit cast for me.
In short: If the programmer uses an explicit cast, the compiler takes the freedom to search for other explicit cast to get the whole thing going.
So... I tried the same thing with my own classes. Instead of byte and decimal, I used MyByte and Mydecimal. The code looks like this:
class MyDecimal // Simulates a decimal.
{
static public explicit operator MyByte(MyDecimal a) // Just like in a decimal.
{
return new MyByte();
}
}
class MyByte // Simulates a byte.
{
}
class MyNumber // Just a class.
{
static public explicit operator MyNumber(MyByte b)
{
return new MyNumber();
}
}
MyDecimal d = new MyDecimal();
MyNumber c2 = (MyNumber)d; // <== Will not compile!
The last line will not compile. It gives the error: "Cannot convert type 'DoubleExplicitCasts.Program.MyDecimal' to 'DoubleExplicitCasts.Program.MyNumber'". Well... why not???
So my question is: Why do the explicit operators inside .NET system get a special treatment and my user explicit operators do not?
EDIT
I know this code is not functional and values are not transfered from one instance to another, but that is beside the point.
IMO, that would lead to "happy debugging" and really, really complicated and non-obvious code.
Just imagine 3 or more levels of such user-defined conversions, and how would you search for error, caused by conversion in the middle (e.g such conversion was introduced by mistake or not supposed to be used in that situation).
Thanks God such behaviour is not supported.
Well, trivially, because that's how it's defined by the C# standard.
From section 6.4.3:
Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. In other words, a conversion from type S to type T will never first execute a user-defined conversion from S to X and then execute a user-defined conversion from X to T.
As to why they chose to limit the conversions in that way - that's a different matter. I'm going to propose two possible reasons:
It would allow the possibility of too many "surprising" conversions
It would make the compilation process too slow (possible combinational explosion)
but that's just conjecture on my part.

What is the justification for this Nullable<T> behavior with implicit conversion operators

I encountered some interesting behavior in the interaction between Nullable and implicit conversions. I found that providing an implicit conversion for a reference type from a value type it permits the Nullable type to be passed to a function requiring the reference type when I instead expect a compilation error. The below code demonstrates this:
static void Main(string[] args)
{
PrintCatAge(new Cat(13));
PrintCatAge(12);
int? cat = null;
PrintCatAge(cat);
}
private static void PrintCatAge(Cat cat)
{
if (cat == null)
System.Console.WriteLine("What cat?");
else
System.Console.WriteLine("The cat's age is {0} years", cat.Age);
}
class Cat
{
public int Age { get; set; }
public Cat(int age)
{
Age = age;
}
public static implicit operator Cat(int i)
{
System.Console.WriteLine("Implicit conversion from " + i);
return new Cat(i);
}
}
Output:
The cat's age is 13 years
Implicit conversion from 12
The cat's age is 12 years
What cat?
If the conversion code is removed from Cat then you get the expected errors:
Error 3 The best overloaded method match for 'ConsoleApplication2.Program.PrintCatAge(ConsoleApplication2.Program.Cat)' has some invalid arguments
Error 4 Argument 1: cannot convert from 'int?' to 'ConsoleApplication2.Program.Cat
If you open the executable with ILSpy the code that was generated is as follows
int? num = null;
Program.PrintCatAge(num.HasValue ? num.GetValueOrDefault() : null);
In a similar experiment I removed the conversion and added an overload to PrintCatAge that takes an int (not nullable) to see if the compiler would perform a similar operation, but it does not.
I understand what is happening, but I don't understand the justification for it. This behavior is unexpected to me and seems odd. I did not have any success finding any reference to this behavior on MSDN in the documentation for conversions or Nullable<T>.
The question I pose then is, is this intentional and is there a explanation why this is happening?
I said earlier that (1) this is a compiler bug and (2) it is a new one. The first statement was accurate; the second was me getting confused in my haste to get to the bus on time. (The bug I was thinking of that is new to me is a much more complicated bug involving lifted conversions and lifted increment operators.)
This is a known compiler bug of long standing. Jon Skeet first brought it to my attention some time ago and I believe there's a StackOverflow question about it somewhere; I do not recall where offhand. Perhaps Jon does.
So, the bug. Let's define a "lifted" operator. If an operator converts from a non-nullable value type S to a non-nullable value type T then there is also a "lifted" operator that converts from S? to T?, such that a null S? converts to a null T? and a non-null S? converts to T? by unwrapping S? to S, converting S to T, and wrapping T to T?.
The specification says that (1) the only situation in which there is a lifted operator is when S and T are both non-nullable value types, and (2) that the lifted and non-lifted conversion operators are both considered as to whether they are applicable candidates for the conversion and if both applicable, then the source and target types of the applicable conversions, lifted or unlifted, are used to determine the best source type, best target type, and ultimately, best conversion of all the applicable conversions.
Unfortunately, the implementation thoroughly violates all of these rules, and does so in a way that we cannot change without breaking many existing programs.
First off, we violate the rule about the existence of lifted operators. A lifted operator is considered by the implementation to exist if S and T are both non-nullable value types, or if S is a non-nullable value type and T is any type to which a null could be assigned: reference type, nullable value type, or pointer type. In all those cases we produce a lifted operator.
In your particular case, we lift to nullable by saying that we convert a nullable type to the reference type Cat by checking for null. If the source is not null then we convert normally; if it is, then we produce a null Cat.
Second, we violate thoroughly the rule about how to determine the best source and target types of applicable candidates when one of those candidates is a lifted operator, and we also violate the rules about determining which is the best operator.
In short, it is a big mess that cannot be fixed without breaking real customers, and so we will likely enshrine the behaviour in Roslyn. I will consider documenting the exact behaviour of the compiler in my blog at some point, but I would not hold my breath while waiting for that day if I were you.
And of course, many apologies for the errors.

What is the difference between explicit and implicit type casts?

Can you please explain the difference between explicit and implicit type casts?
This is a little tricky because the "cast" syntax in C# actually does a range of different things (cast, primitive convert, bespoke convert, etc)
In an implicit cast, there is an obvious reference-preserving conversion between the two:
List<int> l = new List<int>();
IList<int> il = l;
The compiler can prove that this is safe just from static analysis (List<int> is always an IList<int>)
With an explicit cast, either you are telling the compiler that you know more than it does - "please believe me, but check anyway":
List<int> l = new List<int>();
IList<int> il = l;
List<int> l2 = (List<int>)il;
Although this cast is possible, the compiler won't accept that all IList<int>s are actually List<int> - so we must tell it to let it by.
In an implicit primitive conversion (providedby the language spec), it is generally assumed that there is a safe, non-risky, non-lossy (caveat: see Jon's comment) conversion:
int i = 1;
float f = i;
With an explicit primitive conversion, it is likely that the conversion could lose data, or is non-obvious:
float f = 1;
int i = (int)f;
With bespoke operators, all bets are off, and you'd have to look at the documentation. It could be a reference-cast, or it could be anything. It may follow similar rules to primitive conversions (example: decimal), or it could do anything randomly:
XNamespace ns = "http://abc/def"; // implicit
XAttribute attrib = GetAttrib();
int i = (int)attrib; // explicit (extracts text from attrib value and
// parses to an int)
Both of these run custom code that is context-specific.
What's the difference between the President of the United States and the President of Canada?
Since there is no President of Canada, it's hard to answer the question. The right thing to do is to push back and ask for clarification of the question. By "the President of Canada", does the questioner mean the Queen (ceremonial head of state), the Governor General (who can veto bills) or the Prime Minister (who effectively acts as the executive), or something else? Hard to say without clarification.
And even with clarification, it's a vague question. What differences do you want to know about?
Since there is no such thing as an "implicit cast" in C# it is hard to answer your question. In C#, casting is an operator. So I'll push back on it.
Did you mean to ask "what's the difference between an explicit conversion and an implicit conversion?" Or did you mean to ask about the semantics of the cast operator? Or the difference between the cast operator and other type conversion operators? Or situations in which cast operators can be "implicitly" inserted into your code by the compiler? (For example, the foreach loop and the += operator can both implicitly insert an invisible cast.)
Can you clarify the question? What two things are you asking for comparison of, and what sorts of differences are you interested in?
You might consider reading the "Conversions" chapter of the C# specification. Odds are good that any question you have about conversions are answered there.
int i = 2;
float a = i; // Implicit
float b = (float)i; // Explicit
Explicit Conversions
If a conversion cannot be made without a risk of losing information then it is an explicit conversion.
For example -
class ExplicitConversions
{
static void Main()
{
int x;
double y = 6358.057;
// Cast double to int.
x = (int)y;
System.Console.WriteLine(x);
}
}
Implicit Conversions
If a conversion can be made without a risk of losing information then it is an implicit conversion. No special syntax is required because the conversion is type safe and no data is lost.
For example -
class ImplicitConversions
{
static void Main()
{
int x = 6714;
double y;
// Cast int to double.
y = x;
System.Console.WriteLine(y);
}
}
I think this post explains it best.
Explicit cast:
int x = 0;
float y = 3.8f;
x += (int) y; //Explicit cast.
This tells the compiler that the cast was intentional and that you know that the fractional part will go lost. The compiler won't complain.
Implicit cast:
int x = 0;
float y = 3.8f;
x += y; //Implicit cast
The compiler will complain because the fractional part will be lost when converting float to int.
Explicit in MSDN
Implicit in MSDN
A simple search will give lots of informations in the net.
difference between implicit and explicit type
Type Casting: Conversion of one data type to another data type. and it can be done in two ways.
Implicit Type Casting,
Explicit Type Casting
Implicit type casting is performed by the compiler on its own when it encounters a mixed data type expression in the program. it is also known as automatic conversion as it is done by the compiler without the programmer’s assistance. implicit casting doesn’t require a casting operator.
Example:-
int a=42;
float b=a;
here b will contain typecast value of a, because while assigning value to b compiler typecasts the value of an into float then assigns it to b.
Explicit type casting is performed by the programmer. In this typecasting programmer tells the compiler to typecast one data type to another data type using type casting operator. but there is some risk of information loss is there, so one needs to be careful while doing it
Example:-
float a=42.12;
int b=(int)a;
here we explicitly converted float value of a to int while assigning it to int b. (int) is the typecasting operator with the type in which you wants to convert.
Explicit from MSDN -
If a conversion operation can cause exceptions or lose information,
you should mark it explicit. This prevents the compiler from silently
invoking the conversion operation with possibly unforeseen
consequences.
Implicit from MSDN -
if the conversion is guaranteed not to cause a loss of data
From a general point of view; here is the diff between the two type of Casts :
Implicit type casting is performed by the compiler on its own when it encounters a mixed data type expression in the program. it is also known as automatic conversion as it is done by compiler without programmer’s assistance. implicit casting doesn’t require a casting operator.
Explicit type casting is performed by the programmer. In this type casting programmer tells compiler to type cast one data type to another data type using type casting operator. but there is some risk of information loss is there, so one needs to be careful while doing it.
you can refer to This article for more details.

Categories