Implicit versus Explicit cast with parenthesis wrapper - c#

The implicit cast:
FooType Foo = (FooType)someParameter;
The Explicit cast:
FooType Foo = someParameter as FooType;
However, Does double wrapping an implicit cast make it an explicit cast if directly accessing it's properties? Shown below...
string fooName = ((FooType)someParameter).Name;
Nothing critical just curious because I remember reading about implicit casts only getting stored in one place (either stack or heap I forgot) but explicit casts stored it in two places taking up twice as much memory or something so now I try to avoid them if possible.
Nothing critical just curious because I remember reading about implicit casts only getting stored in one place (either stack or heap I forgot) but explicit casts stored it in two places taking up twice as much memory or something so now I try to avoid them if possible.

Both FooType Foo = (FooType)someParameter; and FooType Foo = someParameter as FooType; are explicit casts.
This is an example of an implicit cast:
void Main()
{
BarType bar = new BarType();
FooType foo = bar;
}
class FooType { }
class BarType : FooType { }
Here is another example of an implicit cast:
void Main()
{
int[] values = new int[] { 1, 2, 3 };
Console.WriteLine(Sum(values));
}
int Sum(IEnumerable<int> source) => source.Sum();
Implicit casts are ones that happen automatically without you needing to write explicit code to perform the cast.
The difference between the two examples you gave are that FooType Foo = (FooType)someParameter; will throw an exception at run-time if someParameter cannot be cast to FooType at run-time, however the someParameter as FooType cast will return null if the cast is not valid.
Also, take this example:
void Main()
{
Foo f1 = new Foo(); IFoo f2 = f1;
}
interface IFoo { } class Foo : IFoo { }
Here the new Foo() creates an instance of Foo (allocates memory) and then assigns a reference to that instance to f1. When f1 is assigned to f2 a copy of the reference is made. So you end up with a memory allocation and two references to that memory.
That always happens with refence types - regardless of anything to do with implicit or explicit casts.

Related

Do all C# casts result in boxing/unboxing

I am curious to know if all casts in C# result in boxing, and if not, are all casts a costly operation?
Example taken from Boxing and Unboxing (C# Programming Guide)
int i = 123;
// The following line boxes i.
object o = i;
This line obviously causes boxing (wrapping up the int type as an object).
This is an operation that is considered costly, since it creates garbage that will be collected.
What about casts from 2 different types of reference types? what is the cost of that? can it be properly measured? (compared to the previous example)
For example:
public class A
{
}
public class B : A
{
}
var obj = new B();
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing
I am curious to know if all conversions in C# result in boxing.
No. Only boxing conversions result in boxing, hence the name "boxing conversions". Boxing conversions are all built-in conversions from value types to reference types -- either to a class that the value type inherits from, or to an interface that it implements. (Or to an interface compatible with an interface it implements, via a covariant or contravariant reference conversion.)
are all conversions a costly operation?
No. Identity conversions are zero cost because the compiler can elide them entirely.
What are the costs of implicit and explicit reference conversions?
Implicit reference conversions are zero cost. The compiler can elide them entirely. That is, converting from Giraffe to its base type Animal, or Giraffe to its implemented interface type IAmATallMammal, are free.
Explicit reference conversions involve a runtime check to verify that the reference does in fact refer to an object of the desired type.
Whether that runtime check is "costly" or not depends on your budget.
can that cost be properly measured?
Sure. Decide what resource is relevant to you -- time, say -- and then carefully measure your consumption of time with a stopwatch.
A question you did not ask but probably should have:
What are the most expensive conversions?
User-defined conversions are nothing more than a syntactic sugar for a method call; that method can take arbitrarily long, like any method.
Dynamic conversions start the compiler again at runtime; the compiler may take arbitrarily long to perform a type analysis, depending on how hard an analysis problem you choose to throw at it.
No.
Boxing means putting a value into a new reference type instance.
Standard casts between reference types do not result in any allocations.
(User-defined casts can do anything)
I am curious to know if all casts in C# result in boxing,
No. Boxing is a very special operation that means treating an instance of a value type as an instance of a reference type. For reference type conversion to reference type conversion, the concept plays no role.
are all casts a costly operation?
Short answer: No.
Long answer: Define costly. Still no, though.
What about casts from 2 different types of reference types? what is the cost of that?
Well, what if it's just a derived to base reference conversion? That's BLAZINGLY fast because nothing happens.
Other, user-defined conversions, could be "slow", they could be "fast."
This one is "slow."
class A { public int Foo { get; set; } }
class B {
public int Foo { get; set; }
static Random rg = new Random();
static explicit operator A(B b) {
Thread.Sleep(rg.Next());
return new A { Foo = b.Foo; }
}
}
This one is "fast."
class A { public int Foo { get; set; } }
class B {
public int Foo { get; set; }
static Random rg = new Random();
static explicit operator A(B b) {
return new A { Foo = b.Foo; }
}
}
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing
No, it's "cheap."

Generic unboxing of boxed value types

I have a generic function that is constrained to struct. My inputs are boxed ("objects"). Is it possible to unbox the value at runtime to avoid having to check for each possible type and do the casts manually?
See the above example:
public struct MyStruct
{
public int Value;
}
public void Foo<T>(T test)
where T : struct
{
// do stuff
}
public void TestFunc()
{
object o = new MyStruct() { Value = 100 }; // o is always a value type
Foo(o);
}
In the example, I know that o must be a struct (however, it does not need to be MyStruct ...). Is there a way to call Foo without tons of boilerplate code to check for every possible struct type?
Thank you.
.NET Generics are implemented in a manner that allows value types as a generic type parameter without incurring any boxing/unboxing overhead. Because your're casting to object before calling Foo you don't take advantage of that, in fact you're not even taking advantage of generics at all.
The whole point of using generics in the first place is to replace the "object-idiom". I think you're missing the concept here.
Whatever type T happens to be, it is available at run-time and because you constrained it to struct guaranteed to be a struct type.
Your TestFunc could be written like this without problem:
public void TestFunc()
{
MyStruct o = new MyStruct() { Value = 100 }; // o is always a value type
Foo<MyStruct>(o);
}
Looking at Foo, it would look like this in your example:
public void Foo<T>(T test)
where T : struct
{
T copy = test; // T == MyStruct
}
EDIT:
Ok, since the OP clarified what he wants to call the generic method but doesn't know the type of his struct (it's just object). The easiest way to call your generic method with the correct type parameter is to use a little reflection.
public void TestFunc()
{
object o = new DateTime();
MethodInfo method = this.GetType().GetMethod("Foo");
MethodInfo generic = method.MakeGenericMethod(o.GetType());
generic.Invoke(this, new object[] {o});
}
public void Foo<T>(T test)
where T : struct
{
T copy = test; // T == DateTime
}
No; you're using object, which is (by definition) not a struct/value type. Why are you intentionally boxing the value in this way?
The whole point of using generics is to avoid situations like this.
When you actually "close" the generic with a type of struct, you eliminate the need for runtime type checking: ie.
Foo<MyStruct>(MyStruct test);
Your implementation of Foo, can safely assume that it's dealing with a struct.
(Marked as CW because you can't pass an instance of ValueType to a generic requiring a struct, but it might be helpful for others who come across this question).
Instead of declaring o as an object, you can use a type of System.ValueType, which can only be assigned struct values; you cannot store an object in a ValueType.
However, I'm honestly not sure if that does anything in terms of (un)boxing. Note that ECMA-334 11.1.1 says:
System.ValueType is not itself a value-type. Rather, it is a class-type from which all value-types are automatically derived.
I dont know exactly what you are trying to archieve, but you could pass a delegate/lambda to unbox the value, and select some value in the struct you are interested in:
(Updated this code snippet after slurmomatics comment)
public void Foo<TValue>(object test, Func<object, TValue> ValueSelector)
where TValue : struct
{
TValue value = ValueSelector(test);
// do stuff with 'value'
}
public void TestFunc()
{
object o = new MyStruct() { Value = 100 };
// Do the unboxing in the lambda.
// Additionally you can also select some
// value, if you need to, like in this example
Foo(o, x => ((MyStruct)x).Value);
}
Update:
Then do this:
public static void Foo<TUnboxed>(object test)
where TUnboxed : struct
{
try
{
TUnboxed unboxed = (TUnboxed)test;
}
catch (InvalidCastException ex)
{
// handle the exception or re-throw it...
throw ex;
}
// do stuff with 'unboxed'
}
public void TestFunc()
{
// box an int
object o = 100;
// Now call foo, letting it unbox the int.
// Note that the generic type can not be infered
// but has to be explicitly given, and has to match the
// boxed type, or throws an `InvalidCastException`
Foo<int>(o);
}

Casting Between Data Types in C#

I have (for example) an object of type A that I want to be able to cast to type B (similar to how you can cast an int to a float)
Data types A and B are my own.
Is it possible to define the rules by which this casting occurs?
Example
int a = 1;
float b = (float)a;
int c = (int)b;
Yes, this is possible using C# operator overloading. There are two versions explicit and implicit.
Here is a full example:
class Program
{
static void Main(string[] args)
{
A a1 = new A(1);
B b1 = a1;
B b2 = new B(1.1);
A a2 = (A)b2;
}
}
class A
{
public int Foo;
public A(int foo)
{
this.Foo = foo;
}
public static implicit operator B(A a)
{
return new B(a.Foo);
}
}
class B
{
public double Bar;
public B(double bar)
{
this.Bar = bar;
}
public static explicit operator A(B b)
{
return new A((int)b.Bar);
}
}
Type A can be cast implicitly to type B but type B must be cast explicitly to type A.
Assuming you want that to be an explcit operation you'll need to write an explicit cast operator like so:
public static explicit operator MyTypeOne(MyTypeTwo i)
{
// code to convert from MyTypeTwo to MyTypeOne
}
You can then use it like so:
MyTypeOne a = new MyTypeOne();
MyTypeTwo b = (MyTypeTwo)a;
I'd question whether you want to actually cast one type to another, or whether you actually want to convert instead. I'd say you should avoid writing cast operators for conversions, if you are just aiming to take advantage of a nice syntax :)
Also, in general it is advised not to use implicit casts, as they allow for unintended type converstions. From MSDN documentation on implicit:
However, because implicit conversions
can occur without the programmer's
specifying them, care must be taken to
prevent unpleasant surprises. In
general, implicit conversion operators
should never throw exceptions and
never lose information so that they
can be used safely without the
programmer's awareness.
You cant overload the cast operator in c# but you can use explicit and implicit conversion operators instead:
"Using Conversion Operators (C# Programming Guide)"

Casting between classes that share the same interface

I have two interfaces IHeaderRow, and IDetailRow
I then have an object that implements both RawRow:IHeaderRow, IDetailRow
I then need to cast it to HeaderRow which implements IHeaderRow.
But when I try, it ends up being null or giving an exception.
I can cast ObjectRawRow to either interface IHeaderRow, or IDetailRow
var ObjectIHeaderRow = ObjectRawRow as IHeaderRow;
var ObjectIDetailRow = ObjectRawRow as IDetailRow;
But I can not cast ObjectRawRow to HeaderRow , or ObjectIHeaderRow to HeaderRow.
It throws the error Cannot convert source type 'IA' to target type 'A'
I need to cast it into the actual class HeaderRow.
Thoughts?
EDIT:
Even though setting up an explicit cast took care of the issue I thought I'd provide an answer to the people wondering, WHY I was doing what I was.
In short, I'm sequentially processing a file. Line by line. I read the row into RawRow, and until I look at a few values, I don't actually know what type of row it is going to be. I then wanted to cast it to the proper type.
You can only implicitly cast objects to types they inherit from or implement - since RawRow doesn't derive from HeaderRow, it's not possible.
Depending on your requirements, you could overcome this by writing an explicit conversion operator, creating a HeaderRow constructor that accepts a RawRow as its prototype, or by modifying your code to operate on an IHeaderRow.
Why do you need to cast it to a HeaderRow in the first place? If IHeaderRow produced the api that a HeaderRow implements, than you should just be able to act on IHeaderRow "objects" using the defined methods.
The point of an interface is so that you can treat a grouping of different objects as a similar type. Not so that you can cast different objects between classes that are not linked by inheritance.
First, why do you need to do such a weird cast? There's probably another design for what you're trying to do.
Second, the reason you can't do the cast is because a RawRow isn't an HeaderRow. The only guarantee it makes is that it implements IHeaderRow. The problem is that it has a bunch of other stuff too, stuff that HeaderRow doesn't have. And vice versa - HeaderRow probably has a bunch of stuff that ObjectRawRow doesn't have.
Imagine your classes look like this:
interface IHeaderRow
{
string GetText();
}
class HeaderRow : IHeaderRow
{
public string GetText()
{
return "My Label";
}
public int GetFoo()
{
return 42;
}
}
class ObjectRawRow : IHeaderRow
{
public string GetText()
{
return "My Raw Label";
}
}
Now if you do this, you're ok:
ObjectRawRow row = new ObjectRawRow();
IHeaderRow header = row as IHeaderRow;
string label = header.GetText(); // fine, since GetText is guaranteed to exist
But try this on for size:
ObjectRawRow row = new ObjectRawRow();
HeaderRow header = row as HeaderRow;
int magic = header.GetFoo(); // BOOM! Method doesn't exist,
// because the object isn't really a HeaderRow under the covers.
// It's still really an ObjectRawRow. What do you do now? Crash hard is what.
And that's why you can't cast outside of the inheritance tree.
You cannot cast ObjectRawRow to HeaderRow unless one inherits from the other.
Interfaces have nothing to do with it.
Consider:
class Shape
interface IHasCorners
class Rectangle : IHasCorners, Shape
class Triangle : IHasCorners, Shape
Rectangle myRectangle = new Rectangle();
Triangle myTriangle = new Triangle();
//upcasts
Shape s = (Shape)myRectangle;
IHasCorners hc = (IHasCorners)myRectangle;
//downcasts
Rectangle r2 = (Rectangle)s;
r2 = (Rectangle)hc;
//upcasts
s = (Shape)myTriangle;
hc = (IHasCorners) myTriangle;
//these downcasts won't work
//the variables now reference a Triangle instance
Rectangle r3 = (Rectangle)s;
r3 = (Rectangle)hc;
You will not be able to make this cast unless there is an inheritance relationship between the types. If that is not possible then the best you can do is create an explicit conversion operator that allows you to cast one type as another type.
If you do create an explicit conversion you should understand that this will be slower than casting as you will be invoking an method that will do work as opposed to casting which only changes the reference type and doesn't change any of the memory on the heap.
Consider this example that doesn't compile:
class Example
{
static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
class Foo { }
class Bar { }
Since there is no inheritance relations between the types nor is there an explicit conversion from Foo to Bar this cannot compile.
But adding an explicit conversion allows it to compile:
class Example
{
static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
class Foo
{
public static explicit operator Bar(Foo foo)
{
return new Bar();
}
}
class Bar { }
You can only cast an instance to a particular class if the object is actually an instance of that class (or is derived from that class).
It is not possible to cast an instance of class A to completely unrelated class B (which is what you're trying to do), even if they implement the same interfaces.
You can use the explicit keyword to create methods that will be called when you try to cast from IA to A. The reason it doesn't work without you writing your own method is because the compiler doesn't know what to do with the values that aren't being provided.

C# - Problem with generics and inheritance

I've got a problem with inheritance and generics.
This is the code that illustrates my problem:
namespace TestApplication
{
public class MyClass<T>
{
private T field;
public MyClass(T field)
{
this.field = field;
}
}
public class MyIntClass : MyClass<int>
{
public MyIntClass(int field)
: base(field)
{
}
}
}
And when I try to do something like this:
MyClass<int> sth = new MyClass<int>(10);
MyIntClass intsth = (MyIntClass) sth;
I receive cast exception: Invalid cast exception. Unable to cast 'TestApplication.MyClass`1[System.Int32]' to 'TestApplication.MyIntClass'.
What is more I cannot create cast operator:
public static implicit operator MyIntClass(MyClass<int> myClass)
because: 'TestApplication.MyIntClass.implicit operator TestApplication.MyIntClass(TestApplication.MyClass)': user-defined conversions to or from a base class are not allowed
I need to create casts as described above. I don't know why I cannot cast from a type that is the base class. How can I solve this problem?
Thanks in advance.
Edit
Thanks for Your answers.
Now I see that i cannot convert from a base class to derived class and i see that it doesn't have anything to do with generics.
But why i cannot create user-defined conversions from a base class? I have a method that returns the base class. I am able to define a conversion method but creating a cast operator imho would be a better solution.
You can only cast from a base class to a derived class if the object is actually of type derived class. I mean, you can't cast an instance of base (MyClass<int>) to MyIntClass. You can, however cast it if it was actually of type MyIntClass stored as an MyClass<int> instance.
MyClass<int> foo = new MyIntClass();
MyIntClass bar = (MyIntClass)foo; // this works.
Assume:
class Base {
int x;
}
class Derived : Base {
int y;
}
Base foo = new Base();
Derived bar = (Derived)foo;
if it was allowed, what would the value of bar.y be?
In fact, converting from Derived to Base is not a conversion at all. It's just telling the compiler to let the variable of type Base to point to an object of type Derived. It is possible since derived has more or equal features than Base which is not the case in the other way around.
If you were able to create a conversion operator between base and derived classes, the C# compiler would be unable to distinguish it from the built in relationships defined for them. This is why you cannot create cast operators along inheritance hierarchies.
The other answers so far are correct, but I'd like to point out that your example has nothing to do with generics. It's the equivalent of:
using System;
class Base {}
class Child : Base {}
class Test
{
static void Main()
{
Base b = new Base();
// This will throw an exception
Child c = (Child) b;
}
}
In the comments you asked:
But why conversion from a base class is not allowed?
Simple - it would make no sense. Consider the example:
class BaseClass
{
public int x;
public BaseClass(int StartX)
{
this.x = StartX;
}
}
class ChildClass: BaseClass
{
public int Y;
public BaseClass(int StartX, StartY): base(StartX)
{
this.y = StartY;
}
}
class Program
{
public static void Main()
{
BaseClass B = new BaseClass(3);
ChildClass C = (ChildClass)B;
Console.WriteLine(C.y);
}
}
What do you suppose this program would output, assuming the cast worked? Even worse - imagine that BaseClass has two child classes - ChildClassA and ChildClassB. Do you want this to work?
ChildClassA A = new ChildClassA();
BaseClass bc = (BaseClass)A;
ChildClassB B = (ChildClassB)bc;
This would effectively allow to cast ChildClassA instances to ChildClassB - completely wrong.
As Mehrdad stated, you cannot downcast an object. Upcasting is implicit, therefore you cannot overwrite it.
As for the implicit operator, you can still create a constructor in the derived class which receives a parameter of type baseclass.
If you need to cast freely, define the variable as baseclass, but instantiate derived classes.
As has been said, you're trying to cast an object into a type that it doesn't derive from. Did you perhaps want to do this:
MyClass<int> sth = new MyIntClass(10);
MyIntClass intsth = (MyIntClass) sth;
Instead of creating an MyIntClass, try an alias:
using MyClass<int> = What.Ever.Namespace.MyIntClass;
This is now valid:
MyClass<int> foo = new MyClass<int>();
MyIntClass bar = (MyIntClass)foo;
Just understand that when doing the using alias, you have to qualify your namespace on the alias type name (What.Ever.Namespace).
Regarding your second question:
But why i cannot create user-defined conversions from a base class?
Well, suppose you have this scenario
class Base {
}
class Derived {
public static operator Derived(Base b) { ... }
}
and you tried to do this
Base x = new Derived();
Derived y = (Derived)x;
should the conversion be called? Of course not! The value inside x is actually of type Derived, so the cast is direct, without conversion. But if the value was not of type Derived, but a concrete Base, then the user-defined conversion has to happen because otherwise we'd have a compiler error. This all makes no sense; user-defined conversions are found in compile-time, and the type of the value of x is only known in runtime. Therefore, the compiler would not know what to do - call the user-defined conversion or simply cast the value...
Hope this makes a bit of sense to you.
Answering to your last edit.
This code does already compile, it only fails at runtime:
MyIntClass intsth = (MyIntClass) sth;
So, the following cast operator would be redundant if left explicit:
public static implicit operator MyIntClass(MyClass myClass)
So, the compiler should prevent you from adding that conversion. I think the error might be confusing, but I think it just forbids converting class B to class A if B is derived from A (the warning seemed to me to prevent any conversion to A, at first).
If the operator is made implicit, it is also dangerous, because a downcasting can always fail, so you have to:
show the compiler that you know that, by adding an explicit cast;
show the reader (which includes yourself, minutes later) that the operation might fail.
Assignment/conversion of a base class to a derived class makes sense if you consider assignment or conversion to be a value by value copy. What's confusing about c# for
newbies is the inconsistent way it does things:
'int' is a 'simple' type:
int i = 5; // <- this creates an int.
int j = i; // <- this creates another int and copies the value of i into j.
'Object' is not a simple type:
Object a; // <- this does not create a copy of 'Object', only a reference to one
Object b = new Object(); // <- this actually creates an Object
a = b; // <- this sets the reference to an object a to the reference to an object b.
// both of them reference the same Object. No values were copied.
If it were doing a copy of values then copying to base class to a derived class would
work. C# doesn't work like other languages.
I think that might be what's confusing you.

Categories

Resources