3 general c# questions

J

Jarlaxle

I have 2 general c# questions I was hoping someone could answer...

1. Is it possible to return a struct by ref?...

class A
{
private mystruct _ms = new mystruct();

public mystruct ms
{
get { return _ms; }
}
}

since ms is a struct it returns a copy can therefore can't set values
on it. I think you should be able to doe something like...

get { return ref _ms; }

Any reason why this is not possible or any workarounds instead of making a
class or exposing the member directly?

2. is it possible to call a constructor with a base class?...

class A
{
A(B obj) {...}
A(C obj) {...}
}

object myo = MethodThatReturnsObjectOfBOrC();
A mya = new mya(myo);

Problem is I'd like to not know what could be returned from
MethodThatReturnsObjectOfBOrC so I'd like to avoid a switch statement. (could
add new types in future).

is it possible to cast at runtime and have the constructor address resolved
at runtime?...

Type t = myo.GetType();
A mya = new mya((t)myo);

Thanks.
 
J

Jon Skeet [C# MVP]

Jarlaxle said:
I have 2 general c# questions I was hoping someone could answer...

1. Is it possible to return a struct by ref?...

No. There's no such concept as "return by reference".
class A
{
private mystruct _ms = new mystruct();

public mystruct ms
{
get { return _ms; }
}
}

since ms is a struct it returns a copy can therefore can't set values
on it. I think you should be able to doe something like...

get { return ref _ms; }

Any reason why this is not possible or any workarounds instead of making a
class or exposing the member directly?

If you want reference type semantics, make the type involved a
reference type.
2. is it possible to call a constructor with a base class?...

class A
{
A(B obj) {...}
A(C obj) {...}
}

object myo = MethodThatReturnsObjectOfBOrC();
A mya = new mya(myo);

No. There'd be no compile-time guarantee that you wouldn't be passing
in something completely different. Overloading is performed at compile
time, not execution time.
Problem is I'd like to not know what could be returned from
MethodThatReturnsObjectOfBOrC so I'd like to avoid a switch statement. (could
add new types in future).

is it possible to cast at runtime and have the constructor address resolved
at runtime?...

Type t = myo.GetType();
A mya = new mya((t)myo);

No. Casting is a mostly compile-time construct.
 
B

Ben Voigt [C++ MVP]

Jarlaxle said:
I have 2 general c# questions I was hoping someone could answer...

1. Is it possible to return a struct by ref?...

Not in C#. C++/CLI can...
 
J

Jarlaxle

thanks for the info.
If you want reference type semantics, make the type involved a
reference type.

Yes it looks like that is the best way. Its just sometimes I like creating
structs for simple datatypes such as...

struct MyData
{
public MyData(int x, int y) {...}
int X;
int Y;
}

then is there not a difference in this statement when its a struct vs class...

MyData[] _data = new MyData[10];

you would either be creating 10 MyData pointers or 10 MyData. so i think
there is definite value in being able to return by ref especially for
efficiency.
No. There'd be no compile-time guarantee that you wouldn't be passing
in something completely different. Overloading is performed at compile
time, not execution time.

I think I can accomplish the runtime binding by using reflection...

ConstructorInfo ci = typeof(myobject).GetConstructor(new Type[] {
myitem.GetType() });
if (ci == null)
{
throw ...
}
newobject = ci.Invoke(new object[] {myitem});

of course this is different then casting at compile time like you said but
accomplishes the runtime constructor selection.

Thanks again for the info.
 
J

Jarlaxle

thanks...yes i'm so used to c++ pointers and references it seemed it should
be possible.

do you think it was left out to distinguish value/ref types in c# or do you
think it may be added in the future?
 
B

Ben Voigt [C++ MVP]

Jarlaxle said:
thanks...yes i'm so used to c++ pointers and references it seemed it
should be possible.

do you think it was left out to distinguish value/ref types in c# or
do you think it may be added in the future?

I think you may be able to return a pointer in C# if you use the 'unsafe'
keyword. The C++/CLI compiler probably generates the same IL.

What I don't like about the .NET implementation of pointers is that it
considers all pointers to be unsafe.... they aren't. Only casting or
pointer arithmetic (that results in a new pointer) break type safety.
 
P

Peter Duniho

Yes it looks like that is the best way. Its just sometimes I like
creating
structs for simple datatypes such as...

struct MyData
{
public MyData(int x, int y) {...}
int X;
int Y;
}

But if you want to pass an instance of that data structure around using
reference semantics, you should be using a reference type (i.e. a class)..
Which is what Jon wrote.
then is there not a difference in this statement when its a struct vs
class...

MyData[] _data = new MyData[10];

There is a difference, yes. With a struct, each element of the array is
initialized to the default value for the struct, whereas for a class, each
element of the array is initialized with null and you'd have to explicitly
create a new instance of your class for each array element.

That said, it's not really all that difficult to perform that
initialization. It's a little more work than initializing an array of
value types, but it's not like it's a big deal.
you would either be creating 10 MyData pointers or 10 MyData. so i think
there is definite value in being able to return by ref especially for
efficiency.

Well, for better or worse, C# makes a very clear delineation between value
types and reference types. For reasonably small structs (and IMHO, that
describes all good structs), returning the struct by value would not
create a perceptible loss of efficiency.

Besides, even if C# offered a way to return a struct by reference, the
struct is still fundamentally a value type. So as soon as you try to use
that reference you're going to wind up copying the data, incurring the
exact same performance penalty (if any) that returning it by value might
have caused.

The bottom line, just as Jon already pointed out, if you want to treat
your data using reference semantics, you need to make it a reference type.
I think I can accomplish the runtime binding by using reflection...

Maybe. But IMHO it would be better to provide a static factory method in
the class in question that incorporates the switch logic. For example:

class A
{
public A(B b) { }
public A(C c) { }

public static A FromObject(object obj)
{
if (obj is B)
{
return new A((B)obj);
}
else if (obj is C)
{
return new A((C)obj);
}
else
{
// handle error, e.g. throw exception or return null
}
}
}

You'd just call it like this:

object obj = ReturnsBOrC();
A a = A.FromObject(obj);

Then at least any code that might not know what object it's using to
instantiate A doesn't need to repeat that logic. It's also clearer than
using reflection, and probably performs better too.

Pete
 
J

Jon Skeet [C# MVP]

Jarlaxle said:
thanks for the info.


Yes it looks like that is the best way. Its just sometimes I like creating
structs for simple datatypes such as...

struct MyData
{
public MyData(int x, int y) {...}
int X;
int Y;
}

Why? What makes you prefer a struct in that case?
then is there not a difference in this statement when its a struct vs class...

MyData[] _data = new MyData[10];

you would either be creating 10 MyData pointers or 10 MyData.

When MyData is a struct, that will create 10 instances of MyData
(although effectively for free - just clearing enough memory).

When MyData is a class, the array will be initialized with null
references.
so i think there is definite value in being able to return by ref
especially for efficiency.

As I said before, there's no such concept in C# - you *pass* by
reference, but "return by reference" is meaningless. You could return a
pointer, which is a similar concept, but it wouldn't be the same.

I would avoid worrying about efficiency without doing actual
measurements though.
No. There'd be no compile-time guarantee that you wouldn't be passing
in something completely different. Overloading is performed at compile
time, not execution time.

I think I can accomplish the runtime binding by using reflection...

ConstructorInfo ci = typeof(myobject).GetConstructor(new Type[] {
myitem.GetType() });
if (ci == null)
{
throw ...
}
newobject = ci.Invoke(new object[] {myitem});

of course this is different then casting at compile time like you said but
accomplishes the runtime constructor selection.

It's interesting that you worry about the efficiency of returning data
"by value" vs "by reference", but you are willing to use reflection for
constructor calls. I know which is more likely to have a significant
performance impact...

Seriously, try to avoid doing this - the code will be significantly
harder to follow. Design your way out of needing it, if at all
possible.
 
J

Jarlaxle

Jon Skeet said:
Jarlaxle said:
thanks for the info.


Yes it looks like that is the best way. Its just sometimes I like creating
structs for simple datatypes such as...

struct MyData
{
public MyData(int x, int y) {...}
int X;
int Y;
}

Why? What makes you prefer a struct in that case?
then is there not a difference in this statement when its a struct vs class...

MyData[] _data = new MyData[10];

you would either be creating 10 MyData pointers or 10 MyData.

When MyData is a struct, that will create 10 instances of MyData
(although effectively for free - just clearing enough memory).

When MyData is a class, the array will be initialized with null
references.
so i think there is definite value in being able to return by ref
especially for efficiency.

As I said before, there's no such concept in C# - you *pass* by
reference, but "return by reference" is meaningless. You could return a
pointer, which is a similar concept, but it wouldn't be the same.

I would avoid worrying about efficiency without doing actual
measurements though.

I really don't understand why you say "return by reference" is meaningless.
if you can pass by reference then returning by reference is the same thing.
I understand though that there is no concept in c#.

No. There'd be no compile-time guarantee that you wouldn't be passing
in something completely different. Overloading is performed at compile
time, not execution time.

I think I can accomplish the runtime binding by using reflection...

ConstructorInfo ci = typeof(myobject).GetConstructor(new Type[] {
myitem.GetType() });
if (ci == null)
{
throw ...
}
newobject = ci.Invoke(new object[] {myitem});

of course this is different then casting at compile time like you said but
accomplishes the runtime constructor selection.

It's interesting that you worry about the efficiency of returning data
"by value" vs "by reference", but you are willing to use reflection for
constructor calls. I know which is more likely to have a significant
performance impact...

Seriously, try to avoid doing this - the code will be significantly
harder to follow. Design your way out of needing it, if at all
possible.

well you assume I was talking about the same application. or even the same
part of an application. there is a time for efficiency and a time for
extensibility.
 
J

Jon Skeet [C# MVP]

Jarlaxle said:
I really don't understand why you say "return by reference" is meaningless.
if you can pass by reference then returning by reference is the same thing.

Well, I find it hard to see how it could be the *same* thing.

Passing by reference means that the parameter and argument are aliased.
A change to one variable is immediately reflected in the other.

Now, this is always feasible because while the called method is
executing the calling method is still present - so the argument can't
just vanish.

What would happen if you returned a local variable when "returning by
ref"? The variable would have gone by the time the method completed. Or
would that be disallowed? Or would the variable have been captured.

Maybe it isn't completely meaningless - but I'd certainly rather live
without it, personally.
well you assume I was talking about the same application. or even the same
part of an application. there is a time for efficiency and a time for
extensibility.

True, I was making that assumption. I can't say I'd want either
solution in code I was trying to maintain, however.
 
B

Barry Kelly

Ben said:
What I don't like about the .NET implementation of pointers is that it
considers all pointers to be unsafe.... they aren't. Only casting or
pointer arithmetic (that results in a new pointer) break type safety.

Or pointers to stack-allocated objects that escape their activation
record - which would be easily doable when returning a reference, akin
to returning a ref to a temporary in C++.

Also, interior pointers are only allowed on the stack in the CLR AFAIK,
and so the GC probably has special knowledge that isn't generalized -
you wouldn't be able to store those pointers in fields on the heap. It's
likely performance concerns that causes the GC to only support them in
locals.

Within those constraints, pointers are indeed type-safe. But those
constraints are pretty constraining: they effectively limit the use of
pointers to just being references to (the start of) value types, where
pointers are themselves value types. If one needs pointers within those
constraints, just use a reference type instead. It's not a large extra
cost.

-- Barry
 
W

Willy Denoyette [MVP]

Jon Skeet said:
Well, I find it hard to see how it could be the *same* thing.

Passing by reference means that the parameter and argument are aliased.
A change to one variable is immediately reflected in the other.

Now, this is always feasible because while the called method is
executing the calling method is still present - so the argument can't
just vanish.

What would happen if you returned a local variable when "returning by
ref"? The variable would have gone by the time the method completed. Or
would that be disallowed? Or would the variable have been captured.

In that case of a value type (which is what we are discussing right?), that
would mean that, or:
- the callee would need to allocate the "value" on the heap (but not the GC
heap) instead of on the stack, or,
- the callee would have to copy the stack allocated "value" to the heap and
return a pointer to that "value" .
For obvious reasons, I must say I don't like none of these.

Willy.
 
B

Ben Voigt [C++ MVP]

Jon said:
Well, I find it hard to see how it could be the *same* thing.

Passing by reference means that the parameter and argument are
aliased. A change to one variable is immediately reflected in the
other.

Now, this is always feasible because while the called method is
executing the calling method is still present - so the argument can't
just vanish.

What would happen if you returned a local variable when "returning by
ref"? The variable would have gone by the time the method completed.
Or would that be disallowed? Or would the variable have been captured.

Maybe it isn't completely meaningless - but I'd certainly rather live
without it, personally.

Not having it is a royal pain. What does this code do (assume the index i
refers to an element that exists)?

struct Abc {
int a;
double b;
string c;
}

Abcs.a = 15;

Well, it depends on whether Abcs is an array or a list, and IMHO that is
just plain stupid.
 
J

Jon Skeet [C# MVP]

Not having it is a royal pain.

Can't say I remember *ever* wanting it.
What does this code do (assume the index i
refers to an element that exists)?

struct Abc {
int a;
double b;
string c;
}

Abcs.a = 15;

Well, it depends on whether Abcs is an array or a list, and IMHO that is
just plain stupid.


Well, at least it will fail to compile if it's a list, rather than just
silently failing to do anything.

The moral is to avoid mutable value types though...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top