I did an online assessment and I'm trying to understand the results, and here are a few of the questions I did already:
Get enum value from string
Change to method declaration
So the question is this:
I got this one partially right as well, after reading about the subject I would choose just option A and D, can you guys confirm?
Thanks a lot.
Marco
An implicit conversion does not need a cast:
int a = 10;
long b = a;
An explicit conversion does need a cast:
long a = 10;
int b = (int)a;
To define (not invoke) an implicit conversion, the implicit keyword is used:
public static implicit operator MyOther(MyThis obj);
To define an explicit conversion, the explicit keyword is used:
public static explicit operator MyOther(MyThis obj);
Usually, explicit conversions are used when information might be lost through the conversion, or an exception may occur. For example, converting a 64-bit long integer to a 32-bit int integer might lose the 32 most-significant bits of information.
So, I am sure A is true, B, C and E are false. I don't understand the question for D. If they mean invoking the implicit conversion, then it is false. If they mean defining the implicit conversion, then it is true.
Related
Writing implicit and explicit type conversion operators is trivial.
I can find lots of documentation about how to write them, but very little about when, or why to write them.
I've done some investigations into existing implementations; for example, BigInteger from .NET's reference source:
public struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
{
public static implicit operator BigInteger(Byte value)
{
return new BigInteger(value);
}
public static explicit operator Byte(BigInteger value)
{
return checked((byte)((int)value));
}
}
Given the excerpt above, what is the rational for using an implicit operator when converting from Byte to BigInteger, but using an explicit operator when converting from BigInteger to Byte?
As I mentioned in my comment, my assumption was that implicit operators should always be considered safe, whereas explicit operators may be safe but in some cases may need to be handled.
I found the following documentation on pre-defined implicit operators:
The pre-defined implicit conversions always succeed and never cause
exceptions to be thrown.
Note: Properly designed user-defined implicit conversions should
exhibit these characteristics as well. end note
In addition, the documentation for explicit conversions does not give the same guarantees:
The explicit conversions that are not implicit conversions are
conversions that cannot be proven always to succeed, conversions that
are known possibly to lose information, and conversions across domains
of types sufficiently different to merit explicit notation.
This clearly backs up my assumption that implicit operators must ALWAYS be safe and never require exception handling, whereas explicit operators can and do throw exceptions, as in your example of the explicit operator that is checked.
public static explicit operator int(Author a)
{
return a.Publications.Length;
}
public static implicit operator int(Author a)
{
return a.Publications.Length;
}
why can`t I do this? my teacher asked me to override the implicit and explicit cast for operator int for the Author class. + can I get a explanation for the deep copy :D?
why can`t I do this?
You can't do that because the C# specification says that you cannot, in section 10.10.3.
[...] a class or struct cannot declare both an implicit and an explicit conversion operator with the same source and target types.
Now you might well say:
Answering a "why" question with "because that's what it says in the spec" is deeply unsatisfying.
You asked a vague question. If you want a more specific answer then ask a more specific question. How about:
What factors might the C# design team have considered when creating this rule?
Any implicit conversion is already a legal explicit conversion. That is, if there is an implicit conversion that allows:
Shape s = whatever;
Fruit f = s;
then
Fruit f = (Fruit)s;
is also legal and must mean the same thing. It would be bizarre if those two statements had different semantics, but in a world where you could declare two different versions of the same conversion, one explicit and one implicit, then the compiler would have to detect this situation and ensure that the right conversion is used.
Conversion logic, particularly user-defined conversion logic, is extremely complex in C#. Removing unnecessary, confusing complications is a good idea.
can I get a explanation for the deep copy
Don't ask two questions in one question. Post a second question if you have a second question.
I suspect your seeing compiler error CS0557.
FYI, if you have an implicit operator there is no need for an explicit too. Implicit means there is no need to do a direct cast.
Explicit:
Author a = new Author();
int i = (int)a;
Implicit:
Author a = new Author();
int i = a;
Why does the first and second Write work but not the last? Is there a way I can allow all 3 of them and detect if it was 1, (int)1 or i passed in? And really why is one allowed but the last? The second being allowed but not the last really blows my mind.
Demo to show compile error
using System;
class Program
{
public static void Write(short v) { }
static void Main(string[] args)
{
Write(1);//ok
Write((int)1);//ok
int i=1;
Write(i);//error!?
}
}
The first two are constant expressions, the last one isn't.
The C# specification allows an implicit conversion from int to short for constants, but not for other expressions. This is a reasonable rule, since for constants the compiler can ensure that the value fits into the target type, but it can't for normal expressions.
This rule is in line with the guideline that implicit conversions should be lossless.
6.1.8 Implicit constant expression conversions
An implicit constant expression conversion permits the following conversions:
A constant-expression (§7.18) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
A constant-expression of type long can be converted to type ulong, provided the value of the constant-expression is not negative.
(Quoted from C# Language Specification Version 3.0)
There is no implicit conversion from int to short because of the possibility of truncation. However, a constant expression can be treated as being of the target type by the compiler.
1? Not a problem: it’s clearly a valid short value. i? Not so much – it could be some value > short.MaxValue for instance, and the compiler cannot check that in the general case.
an int literal can be implicitly converted to short. Whereas:
You cannot implicitly convert nonliteral numeric types of larger storage size to short
So, the first two work because the implicit conversion of literals is allowed.
I believe it is because you are passing in a literal/constant in the first two, but there is not automatic type conversion when passing in an integer in the third.
Edit: Someone beat me to it!
The compiler has told you why the code fails:
cannot convert `int' expression to type `short'
So here's the question you should be asking: why does this conversion fail? I googled "c# convert int short" and ended up on the MS C# page for the short keyword:
http://msdn.microsoft.com/en-us/library/ybs77ex4(v=vs.71).aspx
As this page says, implicit casts from a bigger data type to short are only allowed for literals. The compiler can tell when a literal is out of range, but not otherwise, so it needs reassurance that you've avoided an out-of-range error in your program logic. That reassurance is provided by a cast.
Write((short)i)
Because there will not be any implicit conversion between Nonliteral type to larger sized short.
Implicit conversion is only possible for constant-expression.
public static void Write(short v) { }
Where as you are passing integer value as an argument to short
int i=1;
Write(i); //Which is Nonliteral here
Converting from int -> short might result in data truncation. Thats why.
Conversion from short --> int happens implicitly but int -> short will throw compile error bcoz it might result in data truncation.
I have converting this method from vb.net to c#:
Public Shared Widening Operator CType(ByVal items As MyOption()) As MyOptionCollection
Return New MyOptionCollection(items)
End Operator
My complaint is that I do not know what this function can complete. I also want to think of how it is working. I find that "Widening Operator" means that when you cast the cast will work but I don't think I have the full meaning.
How can I convert this to c#? Too can you please send me to where I learn what this does ?
This is a conversion operator that takes array of MyOption references and returns an reference to MyOptionCollection object. "Widening" means that using this conversion, you won't lose any data. "Operator" means that it can be called with special syntax.
In C#, Widening can be replaced with implicit (altough I believe it is not exactly the same). So it'll be:
public static implicit operator MyOptionCollection(MyOption[] items)
{
return new MyOptionCollection(items);
}
You can read about conversion operators in C# at MSDN.
More about widening/narrowing:
When the operator is narrowing, it means that you can possibly lose (some of) your data. Good example is casting from Int64 to Int32. If the value is less than maximal for Int32, the cast will succeed and the value will be persisted. But otherwise it will fail.
Contrary, widening operator can't lose any data, i.e. casting from Int32 to Int64 - you can always do it safely.
A Widening operator is one that can perform a conversion without losing precision/information. As such, it is one that would be safe to declare in C# as an implicit operator.
So the equivalent in C# would be something like:
public static implicit operator MyOptionCollection(MyOption[] items)
{
return New MyOptionCollection(items);
}
Looks like ExpressionTrees compiler should be near with the C# spec in many behaviors, but unlike C# there is no support for conversion from decimal to any enum-type:
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor) x;
ConsoleColor c1 = converter1(7m); // fine
Expression<Func<decimal, ConsoleColor>> expr = x => (ConsoleColor) x;
// System.InvalidOperationException was unhandled
// No coercion operator is defined between types
// 'System.Decimal' and 'System.ConsoleColor'.
Func<decimal, ConsoleColor> converter2 = expr.Compile();
ConsoleColor c2 = converter2(7m);
}
}
Other rarely used C# explicit conversions, like double -> enum-type exists and works as explained in C# specification, but not decimal -> enum-type. Is this a bug?
It is probably a bug, and it is probably my fault. Sorry about that.
Getting decimal conversions right was one of the hardest parts of building the expression tree code correct in the compiler and the runtime because decimal conversions are actually implemented as user-defined conversions in the runtime, but treated as built-in conversions by the compiler. Decimal is the only type with this property, and therefore there are all kinds of special-purpose gear in the analyzer for these cases. In fact, there is a method called IsEnumToDecimalConversion in the analyzer to handle the special case of nullable enum to nullable decimal conversion; quite a complex special case.
Odds are good that I failed to consider some case going the other way, and generated bad code as a result. Thanks for the note; I'll send this off to the test team, and we'll see if we can get a repro going. Odds are good that if this does turn out to be a bona fide bug, this will not be fixed for C# 4 initial release; at this point we are taking only "user is electrocuted by the compiler" bugs so that the release is stable.
Not a real answer yet, I'm investigating, but the first line is compiled as:
Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor)(int)x;
If you try to create an expression from the previous lambda, it will work.
EDIT : In the C# spec, §6.2.2, you can read:
An explicit enumeration conversion
between two types is processed by
treating any participating enum-type
as the underlying type of that
enum-type, and then performing an
implicit or explicit numeric
conversion between the resulting
types. For example, given an enum-type
E with and underlying type of int, a
conversion from E to byte is processed
as an explicit numeric conversion
(§6.2.1) from int to byte, and a
conversion from byte to E is processed
as an implicit numeric conversion
(§6.1.2) from byte to int.
So explicit casts from enum to decimal are handled specifically, that's why you get the nested casts (int then decimal). But I can't see why the compiler doesn't parse the lambda body the same way in both cases.