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);
}
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.
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.
I always thought that the nullable types of the .NET framework where nothing but a nice construct that the framework gave us, but wasn't anything new added to the language itself.
That is, until today, for purposes of a demonstration, I tried to create my own Nullable struct.
I get everything I need, except the capability of doing this:
var myInt = new Nullable<int>(1);
myInt = 1;
The problem is the second statement, as I cannot, by any means, overload the assignment operator.
My question is: Is this a special case in the language where the assignment operator has an overload? If not, how would you approach making that previous example work?
Thanks!
The assignment is question is handled using an implicit operator declared as:
public static implicit operator Nullable<T> (T value)
This is handled without any language-specific features.
The main change to the langauge for nullable support is the ability to write this as:
int? myInt = 1;
You could implement this in your type via:
public static implicit operator Nullable<T> (T value)
{
return new Nullable<T>(value);
}
That being sad, there is a lot of features related to Nullable<T> the C# language and CLR does that can't be duplicated in your code.
Ditto on the other answers, but note that Nullable<T> does do some magic as well.
Quoting from that answer by Lippert
C# automatically lifts operators to nullable. There's no way to say
"automatically lift operators to MyNullable". You can get pretty close
by writing your own user-defined operators though.
C# has special rules for null literals -- you can assign them to
nullable variables, and compare them to nullable values, and the
compiler generates special code for them.
The boxing semantics of nullables are deeply weird and baked into the
runtime. There is no way to emulate them.
Nullable semantics for the is, as and coalescing operators are baked
in to the language.
Nullables do not satisfy the struct constraint. There is no way to
emulate that.
And so on.
Not the assignment operator is overloaded, but the class Nullable<T> specifies an implicit conversion operator which is able to convert T into Nullable<T>.
You can easily add this functionality to your class:
class MyInteger {
private int value;
public MyInteger(int value) { this.value = value; }
public static implicit operator MyInteger(int value) {
return new MyInteger(value);
}
}
And then use the operator in the same way:
MyInteger obj = 123;
According to this page Operator overloading
Note that the assignment operator itself (=) cannot be overloaded.
You can define an implicit operator
I have two or more variables of class object in c# which has integer values. i want to overload '+' operator so that i won't have to convert these variables when ever i want to add or subtract them. here is my code below:
public static object operator +( object obj1, object obj2)
{
object o = Convert.toint32(obj1) + Convert.toint32(obj2);
return o;
}
no the problem is i am getting an error saying "One of the parameters of a binary operator must be the containing type"
why is this happening? any help is appreciated!
The compiler error tells you exactly what's wrong - if you're going to create a custom binary operator, at least one of the parameter types (for the operands) has to be the same as the type you're declaring the operator in (or a nullable version of it, for value types).
This is mandated in section 10.10.2 of the C# 4 specification:
The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:
A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
A binary << or >> operator must take two parameters, the first of which must have type T or T? and the second of which must have type int or int?, and can return any type.
Personally I would try to avoid having variables of type object if you know they're actually int values. Why not have int variables instead?
If you're using C# 4, another alternative would be to make them dynamic variables, where the operator overloading would be applied at execution time rather than compile time.
You can't override the operator for existing classes: only your own classes.
This seems silly/ridiculous, the objects are ints, and because you don't want to cast, you'll make your code less readable by adding objects (which seems crazy)? What happens when you want to do myObj + 1? You'll need to make a massive array of operators and overloads and it's not worth the effort.
Use the correct type in the first place, for the sake of whoever has to read or maintain the code in the future.
You're saying that you want to add two objects of type object, you can't do that.
As the error message says, one of the two parameters to the operator method has to be the type where you defined the operator.
ie. if you declared the operator inside a class with the name XYZ, either obj1 or obj2 has to be of that type.
You cannot declare operator overloads for unrelated types.
Basically, you can't do what you want to do.
The compiler error is telling you exactly the problem.
You can't 'inject' an operator overload into somebody else's types - an operator overload must apply to the type in which you declare it.
The term 'apply' in this case is then explained by the compiler error: one of the parameters must be of that type; the other parameter can be of any type.
So, for example:
public class MyType
{
public static object operator +(MyType obj1, object obj2){
//define code for adding the object to 'MyType' and return object,
//or whatever type you want.
}
}
In this example we are creating an operator between MyType and object and it works because it's defined inside MyType. All binary operator overloads must follow the same rule.
You are defining the operator in a class, let's say class Foo. The compiler tells you that at least one of the two operands must have a static type of Foo, for example:
public static object operator +( Foo obj1, object obj2)
{
object o = Convert.toint32(obj1) + Convert.toint32(obj2);
return o;
}
It's not very clear what you are trying to achieve here. If you have objects of class Foo but their static type is object, then you can't do anything such unless you cast them to Foo first.
In C# i would do something like:
mytype val =
(mytype)mylistview.SelectedItems(0).Tag;
how can I do the same thing in VB.NET?
My VB sucks, but I think it would be:
Dim val as MyType = CType(mylistview.SelectedItems(0).Tag, MyType)
or
Dim val as MyType = DirectCast(mylistview.SelectedItems(0).Tag, MyType)
DirectCast doesn't perform any other conversions - including (IIRC) user-specified conversions, whereas CType will perform more conversions than a cast in C# would
In this particular case, I think DirectCast is probably what you're after, as it should be just a reference conversion.
For the vast majority of cases the CType operator will give the correct behavior here.
Dim val = CType(mylistview.SelectedItems(0).Tag,MyType)
However this is not true in every case. The reason why is that there is no 1-1 mapping between the C# cast operator and an equivalent operator in VB. The C# cast operator supports both CLR and user defined conversion operators.
VB's two main casting operators are DirectCast and CType. DirectCast supports runtime conversions only and will miss user defined ones. CType supports runtime and user defined conversions. But it also supports lexical conversions (such as the string literal "123" to an Integer type). So it will catch everything a C# cast operator does but also include more.
Not sure I'm right not knowing what exactly you're trying to do but general syntax would be:
val = CType(listview.selecteditems(0).tag,mytype)