Reputation: 17293
I'm trying to figure out this piece of ASP.NET C# code. Can someone suggest what am I not doing right here?
When I run the code below I'm expecting strDest to be "New value" and nDest equal to 2, but they remain unchanged...
//These are two variables to fill
string strDest = "";
int nDest = 0;
public enum MyDataType
{
MyTypeString,
MyTypeInt
}
public struct MyStruct
{
public MyDataType type;
public Object objDest;
public MyStruct(MyDataType tType, Object oDest)
{
type = tType;
objDest = oDest;
}
}
//Pass variables by reference
MyStruct[] data2Check = {
new MyStruct(MyTypeString, strDest),
new MyStruct(MyTypeInt, nDest),
};
//And set them
for(int i = 0; i < data2Check.Length; i++)
{
if(data2Check[i].type == MyTypeString)
{
(string)data2Check[i].objDest = "New value";
}
else if(data2Check[i].type == MyTypeInt)
{
(int)data2Check[i].objDest = 2;
}
}
EDIT: OK, Let me re-phrase it. Say, I have a set of variables or members of a class, say 50 of them. They are all of different types. (In this example they are represented by string strDest and int nDest.) OK. Now I also have a two dimensional array of name=value pairs, so each of those pairs should be assigned to my class members depending on the "name". I do the process of determining which "name" goes to what member of the class, and the for() loop below is my abstraction of the assignment process. What seems to be missing is the way to pass my class members by reference into this for() loop so that I can later assign values to them.
PS. So far, none of the examples below do the job...
Upvotes: 2
Views: 498
Reputation: 415820
C# doesn't handle reference vs value quite the same as C++. In C#, everything, even references, are passed by value by default (also: mutable structs are frowned on by several notable c# developers, including stack overflow rep leader Jon Skeet and C# language team lead Eric Lippert).
To get code that does what you're looking for, you do this:
class MyStruct { /* all other code is the same, just make it a class */ }
//These are two variables to fill
MyStruct strDest = new MyStruct(MyDataType.MyTypeString, "");
MyStruct nDest = new MyStruct(MyDataType.MyTypeInt, 0);
//Pass variables by reference -- this will work now because "MyStruct" is actually a reference type
MyStruct[] data2Check = {
strDest, //reference to actual strDest object
nDest, //reference to actual nDest object
};
//And set them
foreach(var item in data2Check) //foreach will work instead of "for", there are some good reasons to prefer this in C#
{
if(item.type == MyDataType.MyTypeString)
{
item.objDest = "New value"; // no need for a cast
}
else if(item.type == MyDataType.MyTypeInt)
{
item.objDest = 2;
}
}
But really, you're pulling in some idioms from the C++ world that make no sense at all for C#. Stick with reference types, and go with a generic when types might vary. I'm not sure what exact problem you're trying to solve, or I could give you some more specific guidance on how to express a solution in idiomatic c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public enum MyDataType
{
MyTypeString,
MyTypeInt
}
public class MyStruct
{
public MyDataType type;
public Object objDest;
public MyStruct(MyDataType tType, Object oDest)
{
type = tType;
objDest = oDest;
}
}
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//These are two variables to fill
MyStruct strDest = new MyStruct(MyDataType.MyTypeString, "");
MyStruct nDest = new MyStruct(MyDataType.MyTypeInt, 0);
//Pass variables by reference -- this will work now because "MyStruct" is actually a reference type
MyStruct[] data2Check = {
strDest, //reference to actual strDest object
nDest, //reference to actual nDest object
};
//And set them
foreach (var item in data2Check) //foreach will work instead of "for", there are some good reasons to prefer this in C#
{
if (item.type == MyDataType.MyTypeString)
{
item.objDest = "New value"; // no need for a cast
}
else if (item.type == MyDataType.MyTypeInt)
{
item.objDest = 2;
}
}
Response.Write(strDest.objDest.ToString() + "<br/>" + nDest.objDest.ToString());
}
}
Upvotes: 3
Reputation: 19881
I'm still not following what you are trying to do ...and as @JoelCoehoorn (and many others) states, you should try to make your value type (struct) immutable. This is kind of ugly, but here's something that works. If I had a better understanding of what you are trying to do, this would probably be much cleaner - I do not advocate production use of this example:
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo( );
foo.Set( );
foreach (var data in foo.data2Check)
{
Console.WriteLine("{0} = {1}", data.type, data.objDest);
}
Console.ReadKey( );
}
}
public class Foo
{
//These are two variables to fill
string strDest = "";
int nDest = 0;
internal List<MyStruct> data2Check;
public Foo( )
{
data2Check = new List<MyStruct>{
new MyStruct(MyDataType.MyTypeString, strDest),
new MyStruct(MyDataType.MyTypeInt, nDest),
};
}
public void Set( )
{
//And set them
for (int i = 0 ; i < data2Check.Count ; i++)
{
if (data2Check[i].type == MyDataType.MyTypeString)
{
data2Check[i] = new MyStruct(data2Check[i].type, "New value");
}
else if (data2Check[i].type == MyDataType.MyTypeInt)
{
data2Check[i] = new MyStruct(data2Check[i].type, 2);
}
}
}
}
public enum MyDataType
{
MyTypeString,
MyTypeInt
}
public struct MyStruct
{
public MyDataType type;
public Object objDest;
public MyStruct(MyDataType tType, Object oDest)
{
type = tType;
objDest = oDest;
}
}
Output:
MyTypeString = New value
MyTypeInt = 2
Upvotes: 0
Reputation: 15893
When you pass strDest
and nDest
to MyStruct
constructors, they are passed by value. The compiler generated code is different for a value type int
and reference type string
. There is boxing done on the value of nDest
(that does not affect the nDest
variable itself). With string
it is the type immutability (or "copy on write" behaviour) that plays the part.
Upvotes: 1