C# 通过引用使用对象的方法

发布于 2024-12-15 16:54:01 字数 1159 浏览 2 评论 0原文

我正在尝试找出这段 ASP.NET C# 代码。有人可以建议我在这里不做什么吗?

当我运行下面的代码时,我期望 strDest 为“新值”并且 nDest 等于 2,但它们保持不变...

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

编辑: 好吧,让我重新表述一下。假设我有一组变量或一个类的成员,比如说 50 个。它们都是不同类型的。 (在此示例中,它们由字符串 strDest 和 int nDest 表示。)好的。现在我还有一个名称=值对的二维数组,因此每个对都应根据“名称”分配给我的类成员。我执行确定哪个“名称”属于类的哪个成员的过程,下面的 for() 循环是我对分配过程的抽象。似乎缺少的是通过引用将我的类成员传递到此 for() 循环中的方法,以便我稍后可以为它们分配值。

附言。到目前为止,下面的例子都没有完成这项工作......

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

若沐 2024-12-22 16:54:01

C# 处理引用与值的方式与 C++ 不同。在 C# 中,默认情况下,所有内容(甚至引用)都按值传递(另外:一些著名的 C# 开发人员不赞成可变结构,包括堆栈溢出代表领导者 Jon Skeet 和 C# 语言团队领导 Eric Lippert)。

要获得满足您需要的代码,您可以这样做:

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

但实际上,您从 C++ 世界中引入了一些对于 C# 毫无意义的习惯用法。坚持使用引用类型,并在类型可能发生变化时使用泛型。我不确定您要解决的具体问题是什么,或者我可以为您提供一些关于如何用惯用的 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());
    }
}

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());
    }
}
宁愿没拥抱 2024-12-22 16:54:01

当您将 strDestnDest 传递给 MyStruct 构造函数时,它们是按值传递的。对于值类型 int 和引用类型 string,编译器生成的代码是不同的。对 nDest 的值进行装箱(不会影响 nDest 变量本身)。对于 string 来说,类型不变性(或“写入时复制”行为)发挥了作用。

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.

心凉怎暖 2024-12-22 16:54:01

我仍然没有遵循你想要做的事情......并且正如@JoelCoehoorn(和许多其他人)所说,你应该尝试使你的值类型(结构)不可变。这有点丑陋,但这里有一些有用的东西。如果我更好地理解你想要做什么,这可能会更清晰 - 我不提倡在生产中使用此示例

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

输出:

MyTypeString = 新值
MyTypeInt = 2

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文