将一个对象发送给一个方法,并将该对象返回给C#

将一个对象发送给一个方法,并将该对象返回给C#,c#,oop,optimization,C#,Oop,Optimization,我目前正在使用C#,但我认为所有OO语言的问题都是一样的 我有一个方法,位于我的“ServersList”类中。在这个方法中,我用反序列化填充ServersList 方法如下: public ServersList fillList(ServersList serversList) { //ServersList serversList = new ServersList(); XmlSerializer serializer = new XmlSerializer(typeof

我目前正在使用C#,但我认为所有OO语言的问题都是一样的

我有一个方法,位于我的“ServersList”类中。在这个方法中,我用反序列化填充ServersList

方法如下:

public ServersList fillList(ServersList serversList)
{
    //ServersList serversList = new ServersList();
    XmlSerializer serializer = new XmlSerializer(typeof(BusinessObjects.ServersList));

    using (StreamReader reader = new StreamReader("Resources/XMLServers.xml"))
    {
        serversList = (BusinessObjects.ServersList)serializer.Deserialize(reader);
    }

    return serversList;
}
我不知道是否最好在Main.cs中创建一个ServersList,使用此SereversList作为参数调用我的方法并返回结果,或者调用不带参数的函数并直接在其中创建ServersList(就像我在注释行中所做的那样)


很抱歉,如果我的问题看起来很愚蠢或是什么的话,我对OOP很陌生,我真的不知道哪种方法是最好的。谢谢你的帮助

我认为传递一个空列表没有任何意义,因为你根本不用它的值。这只会让未来的读者和维护者感到困惑,尤其是在用户方面。我也会让它静止。比较一下:

var serversList = new ServersList();
serversList = serversList.fillList(serversList);
为此:

var serversList = ServersList.LoadFromResources("Resources/XMLServers.xml");
就我个人而言,我宁愿这样写:

public static ServersList LoadList(string _FileName)
    {
        using (StreamReader reader = new StreamReader(_FileName))
        {
            return (BusinessObjects.ServersList)serializer.Deserialize(reader);
        }
    }

顺便说一句,这是一个典型的例子。

如果您只在方法中需要它,请在方法中创建并初始化它。对象仍将保留在堆上,而对它的引用将保留在堆上(在类中声明时)或堆栈上(在方法体中声明时)。这与此无关

绝对没有理由将引用的副本传递给方法,而不打算从中读取并在内部修改它。

查看这一行:

serversList = (BusinessObjects.ServersList)serializer.Deserialize(reader);
方法
反序列化
已经创建了一个新列表,并替换了您拥有的列表。这会使参数和注释行变得无用

我的建议是将方法改为:

public ServersList CreateServersList();
以及实施:

    XmlSerializer serializer = new XmlSerializer(typeof(BusinessObjects.ServersList));

    using (StreamReader reader = new StreamReader("Resources/XMLServers.xml"))
    {
        return (BusinessObjects.ServersList)serializer.Deserialize(reader);
    }
这样,反序列化创建的列表将直接返回给调用方。

不仅不需要将其作为参数传递,而且实际上这是一个非常糟糕的主意。这意味着该方法正在对初始列表执行某些操作,可能会修改其内容,而实际上它正在创建一个全新的实例并返回它

考虑以下代码,例如:

public string DoStuff(string text)
{
    text = "Something else";
    return text;
}
即使不使用返回值,也可以轻松调用此方法:

var text = "My text";

// this compiles
DoStuff(text);

// but the original variable was not changed
Console.WriteLine(text);
但是,至少要考虑删除硬编码字符串并从(比如)配置文件中获取它:

public static ServersList LoadServersList()
{
    var serializer = new XmlSerializer(typeof(ServersList));
    var configFile = ConfigurationManager.AppSettings["ServerListPath"];
    using (var reader = new StreamReader(configFile))
    {
        return (ServersList)serializer.Deserialize(reader);
    }
}

在您的方法中调用反序列化之前,方法参数保留内存上的serversList点,但在进行反序列化时,在serializer.Deserialize()方法中创建的新serversList对象上的serversList点。然后,您不需要在函数的参数中获取他。

此函数中不需要参数。在任何情况下,调用方都看不到此参数中所做的更改。可能更适合这个问题。正如Alex所说,没有必要将
serversList
引用传递到方法中。这实际上是一件坏事,因为调用者可能会认为参数内容将被方法更改。但是,硬编码的文件名不是一个好主意。我认为您发布的代码甚至不起作用,因为您没有为
服务器列表使用
ref
关键字parameter@Ben-你是对的,但这取决于你如何定义“工作”。调用方必须使用返回的值。参数是无用的:如果没有
ref
out
关键字,引用将不会更改,并且传入列表将不会被填充。事实上,我尝试了我的代码,我可以使用静态方法否?如果我理解静态方法的概念,我只需编写
serverslistsrv=ServersList.fillList()
,就可以用数据填充srv列表。是吗?是的。看看我在下面添加的方法示例。是的,我在发表评论后看到了您的代码示例;)谢谢,我会用这个方法!是的,我现在明白了。但是,是否可以更改列表的内容?在您的示例中,是否有方法更改“text”变量?我不知道您是否理解我的意思,我的英语不是很好。@T2o:要么您将其作为(首选)传递,要么从
XmlSerializer
获取新实例,并将所有属性复制到现有实例中。