精简版
对于那些没有时间阅读下面我对这个问题的推理的人:
是否可以对方法的参数实现“仅新对象”或“仅现有对象”策略?
长版
有很多将对象作为参数的方法,并且该方法是否具有“全部自身”的对象并不重要。例如:

var people = new List<Person>();

Person bob = new Person("Bob");

people.Add(bob);
people.Add(new Person("Larry"));
此处List<Person>.Add方法采用了“现有的” Person(Bob)和"new"的Person(Larry),并且列表包含这两项。 Bob可以使用bobpeople[0]进行访问。可以将Larry作为people[1]进行访问,如果需要,可以将其缓存并随后作为larry(或其他任何方式)进行访问。
好的。但有时确实不应将方法传递给新对象。以Array.Sort<T>为例。以下内容并没有多大意义:
Array.Sort<int>(new int[] {5, 6, 3, 7, 2, 1});
上面所有代码所做的就是获取一个新数组,对其进行排序,然后将其忘记(因为在Array.Sort<int>退出后其引用计数达到零,因此,如果我没有记错的话,将对垃圾箱进行排序)。因此,Array.Sort<T>希望将“现有”数组作为其参数。
可以想到还有其他可能期望"new"对象的方法(尽管我通常认为拥有这样的期望将是一个设计错误)。一个不完美的例子是这样的:
DataTable firstTable = myDataSet.Tables["FirstTable"];
DataTable secondTable = myDataSet.Tables["SecondTable"];

firstTable.Rows.Add(secondTable.Rows[0]);
就像我说的那样,这不是一个很好的例子,因为DataRowCollection.Add实际上并不需要一个新的DataRow;但它确实希望DataRow不属于DataTable。因此,上面代码中的最后一行将不起作用;它必须是:
firstTable.ImportRow(secondTable.Rows[0]);
无论如何,这是针对我的问题的大量设置,即:是否可以对方法的参数强制执行“仅新对象”或“仅现有对象”策略(无论是在其定义中(也许是某些情况下)自定义属性(我不知道)还是在方法本身内(也许是通过反射,尽管即使有可能我也会回避)?
如果不是这样,那么关于如何实现此目标的任何有趣想法都将受到欢迎。例如,我假设如果有某种方法可以获取给定对象的GC引用计数,则可以在方法开始时立即告诉您是否收到了新对象(假设您正在处理引用类型) ,当然-这是与此问题相关的唯一情况)。

编辑:
越长的版本越长。
好吧,假设我有一些方法可以选择接受TextWriter来输出其进度或您拥有了什么:
static void TryDoSomething(TextWriter output) {
    // do something...
    if (output != null)
        output.WriteLine("Did something...");

    // do something else...
    if (output != null)
        output.WriteLine("Did something else...");

    // etc. etc.

    if (output != null)
        // do I call output.Close() or not?
}

static void TryDoSomething() {
    TryDoSomething(null);
}
现在,让我们考虑一下可以调用此方法的两种不同方式:
string path = GetFilePath();
using (StreamWriter writer = new StreamWriter(path)) {
    TryDoSomething(writer);

    // do more things with writer
}
或者:
TryDoSomething(new StreamWriter(path));
嗯...看来这是个问题,不是吗?我已经构造了一个StreamWriter,它实现了IDisposable,但是TryDoSomething不会假定知道它是否具有对其output参数的独占访问权。因此,对象要么过早处置(在第一种情况下),要么根本不处置(在第二种情况下)。
我并不是说这肯定是一个很棒的设计。乔什·斯托多拉(Josh Stodola)也许是正确的,从一开始这就是一个坏主意。无论如何,我之所以问这个问题,主要是因为我很好奇这种事情是否可能发生。看起来答案是:并非如此。

最佳答案

不,基本上。

两者之间确实没有区别:

var x = new ...;
Foo(x);


Foo(new ...);

实际上,有时您可能会出于调试目的而在两者之间进行转换。

请注意,在DataRow/DataTable示例中,还有另一种方法-DataRow可以知道其父级作为其状态的一部分。这与是否"new"不是一回事-例如,您可以进行“分离”操作。相对于诸如“new”之类的粗俗术语,用对象的真实的硬性状态来定义条件要有意义得多。

10-07 12:54
查看更多