Passing arguments, does unboxing occur - c#

What I have read, passing arguments is by default valuetypes. In my example the first function test1 takes a reference type and unbox, it will decrease the performance if I got this right.
However I have never read that you do like test2 for increase performance.
So whats best practice?
public Main(){
string test = "hello";
test1(test); // Does this line perform a boxing? So it's not good for performance?
test2(ref test); // Passing a reference as a reference
}
public string test1(string arg1) {
return arg1;
}
public string test2(ref string arg1) {
return arg1;
}

There's no boxing or unboxing involved at all here. string is a reference type - why would it be boxed? What would that even mean?
Even if you used int instead, there'd be no need for boxing, because there's no conversion of the value into an actual object.
I suspect your understanding of both boxing and parameter passing is flawed.
Boxing occurs when a value type value needs to be converted into an object, usually in order for it to be used as a variable (somewhere) of an interface or object type. So this boxes:
int value = 10;
Foo(value);
...
public void Foo(object x)
{
}
... but it wouldn't occur if Foo were changed such that the type of x were int instead.
The detailed rules on boxing become very complicated to state precisely and accurately, particularly where generics come in, but that's the basics.

There is no boxing here at all; boxing is when a value type is treated as object or an interface (not including generics), for example:
int i = 1;
Foo(i); // the value of i is boxed
Bar(i); // the value of i is boxed
...
private void Foo(object obj) {...}
private void Bar(IConvertible obj) {...}
In your examples, a: there is no type conversion here, so no need to box, and b: string is a reference-type anyway, so there is no meaning of boxing a string.
Your test2 is actually showing "pass by reference", aka ref, which is completely unrelated to boxing - and indeed ref parameters must be an exact match, so there is never any boxing involved in a ref parameter (however, subsequent code could obtain the value from the reference and then box/unbox that)

Related

Generic Cast, casting a int to double not possible

I have a dictionary that stores different types of variables (string, double, int, etc.), they are stored as objects.
I have a generic Set method and a generic get method.
private static Dictionary<int, object> dict = new Dictionary<int, object>();
public static void Set<T>(int key, object value)
{
dict.Add(key, (T)value);
}
public static T Get<T>(int key)
{
dict.TryGetValue(key, out object value);
return (T)value;
}
static void Main(string[] args)
{
Set<int>(1, 100);
Get<double>(1);
}
In the Main I'm trying to save the variable 100 as integer, which works, it is stored "as an object" in the dictionary.
Now when trying to Get the variable, casting it to double, the IllegalCastException is thrown, but why?
A explicit cast from object to double is available, as well as a explicit cast from int to double.
You don't cast from object to int or to double. You unbox. And the unboxing rules are clear - you can only take out exactly the same type as you put in. (Insert some caveats around enums and underlying types which aren't exactly relevant to the question at hand)
For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. Attempting to unbox null causes a NullReferenceException. Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.

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."

Most efficient way to check if an object is a value type

WARNING: THIS CODE SUCKS, SEE ANTHONY'S COMMENTS
Which is faster?
1.
public bool IsValueType<T>(T obj){
return obj is ValueType;
}
2.
public bool IsValueType<T>(T obj){
return obj == null ? false : obj.GetType().IsValueType;
}
3.
public bool IsValueType<T>(T obj){
return default(T) != null;
}
4.Something else
You aren't really testing an object - you want to test the type. To call those, the caller must know the type, but... meh. Given a signature <T>(T obj) the only sane answer is:
public bool IsValueType<T>() {
return typeof(T).IsValueType;
}
or if we want to use an example object for type inference purposes:
public bool IsValueType<T>(T obj) {
return typeof(T).IsValueType;
}
this doesn't need boxing (GetType() is boxing), and doesn't have problems with Nullable<T>. A more interesting case is when you are passing object...
public bool IsValueType(object obj);
here, we already have massive problems with null, since that could be an empty Nullable<T> (a struct) or a class. But A reasonable attempt would be:
public bool IsValueType(object obj) {
return obj != null && obj.GetType().IsValueType;
}
but note that it is incorrect (and unfixable) for empty Nullable<T>s. Here it becomes pointless to worry about boxing as we are already boxed.
My first answer would be to write a simple test and find out for yourself.
My second answer (without any testing on my part, of course) would be option 1. It is the simplest check. The second method involves two separate checks while the third involves creating a default instance of a type.
You should also consider readability. The framework already gives you the ability to have the following in your code:
if(someObj is ValueType)
{
// Do some work
}
Why even bother creating a method that would simply turn the above statement into (assuming you made your method static and allowed the compiler to infer the generic type):
if(IsValueType(someObj))
{
// Do some work
}
Defining a struct actually defines two types: a value type, and a class type which derives from System.ValueType. If a request is made to create a variable, parameter, field, or array (collectively, 'storage location') of a type which derives from System.ValueType, the system will instead create a storage location which will store the object's fields rather than storing a reference to an object in which those fields appear. On the other hand, if a request is made to create an instance of a type deriving from System.ValueType, the system will create an object instance of a class which derives from System.ValueType.
This may be demonstrated by creating a struct which implements IValue:
interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
public int value {get; set;}};
}
with generic test routine and code to wrap it:
static void Test<T>(T it) where T:IValue
{
T duplicate = it;
it.value += 1;
duplicate.value += 10;
Console.WriteLine(it.value.ToString());
}
static void Test()
{
ValueStruct v1 = new ValueStruct();
v1.value = 9;
IValue v2 = v1;
Test<ValueStruct>(v1);
Test<ValueStruct>(v1);
Test<IValue>(v1);
Test<IValue>(v1);
Test<IValue>(v2);
Test<IValue>(v2);
}
Note that in every case, calling GetType on the parameter passed to Test would yield ValueStruct, which will report itself as a value type. Nonetheless, the passed-in item will only be a "real" value type on the first two calls. On the third and fourth calls, it will really be a class type, as demonstrated by the fact that a change to duplicate will affect it. And on the fifth and sixth calls, the change will be propagated back to v2, so the second call will "see" it.
static class Metadata<T>
{
static public readonly Type Type = typeof(T);
static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}
//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
//...
}
There are two rules:
1-All Classes are reference types such as Object and String, so it's supported by .NET Framework classes.
2-All structures are value types such as bool and char, even though it contain reference member, so it's supported by .NET Framework structures.
Simply right click on any type and Go To Definition if it's a Class so that means it a reference type else if it's a Struct so that means it's a value type :)
You can use
obj.GetType().IsValueType
This uses reflection but clear way instead of care of boxing unboxing.

Structs, Interfaces and Boxing [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it safe for structs to implement interfaces?
Take this code:
interface ISomeInterface
{
public int SomeProperty { get; }
}
struct SomeStruct : ISomeInterface
{
int someValue;
public int SomeProperty { get { return someValue; } }
public SomeStruct(int value)
{
someValue = value;
}
}
and then I do this somewhere:
ISomeInterface someVariable = new SomeStruct(2);
is the SomeStruct boxed in this case?
Jon's point is true, but as a side note there is one slight exception to the rule; generics. If you have where T : ISomeInterface, then this is constrained, and uses a special opcode. This means the interface can be used without boxing. For example:
public static void Foo<T>(T obj) where T : ISomeInterface {
obj.Bar(); // Bar defined on ISomeInterface
}
This does not involve boxing, even for value-type T. However, if (in the same Foo) you do:
ISomeInterface asInterface = obj;
asInterface.Bar();
then that boxes as before. The constrained only applies directly to T.
Yes, it is. Basically whenever you need a reference and you've only got a value type value, the value is boxed.
Here, ISomeInterface is an interface, which is a reference type. Therefore the value of someVariable is always a reference, so the newly created struct value has to be boxed.
I'm adding this to hopefully shed a little more light on the answers offered by Jon and Marc.
Consider this non-generic method:
public static void SetToNull(ref ISomeInterface obj) {
obj = null;
}
Hmm... setting a ref parameter to null. That's only possibly for a reference type, correct? (Well, or for a Nullable<T>; but let's ignore that case to keep things simple.) So the fact that this method compiles tells us that a variable declared to be of some interface type must be treated as a reference type.
The key phrase here is "declared as": consider this attempt to call the above method:
var x = new SomeStruct();
// This line does not compile:
// "Cannot convert from ref SomeStruct to ref ISomeInterface" --
// since x is declared to be of type SomeStruct, it cannot be passed
// to a method that wants a parameter of type ref ISomeInterface.
SetToNull(ref x);
Granted, the reason you can't pass x in the above code to SetToNull is that x would need to be declared as an ISomeInterface for you to be able to pass ref x -- and not because the compiler magically knows that SetToNull includes the line obj = null. But in a way that just reinforces my point: the obj = null line is legal precisely because it would be illegal to pass a variable not declared as an ISomeInterface to the method.
In other words, if a variable is declared as an ISomeInterface, it can be set to null, pure and simple. And that's because interfaces are reference types -- hence, declaring an object as an interface and assigning it to a value type object boxes that value.
Now, on the other hand, consider this hypothetical generic method:
// This method does not compile:
// "Cannot convert null to type parameter 'T' because it could be
// a non-nullable value type. Consider using 'default(T)' instead." --
// since this method could take a variable declared as, e.g., a SomeStruct,
// the compiler cannot assume a null assignment is legal.
public static void SetToNull<T>(ref T obj) where T : ISomeInterface {
obj = null;
}
The MSDN documentation tells us that structs are value, not reference types. They are boxed when converting to/from a variable of type object. But the central question here is: what about a variable of an interface type? Since the interface can also be implemented by a class, then this must be tantamount to converting from a value to a reference type, as Jon Skeet already said, therefore yes boxing would occur. More discussion on an msdn blog.

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);
}

Categories

Resources