C# 扩展方法和带有ref参数的方法之间有什么区别?

C# 扩展方法和带有ref参数的方法之间有什么区别?,c#,pass-by-reference,extension-methods,C#,Pass By Reference,Extension Methods,更新: 我确实理解基本的C#概念,我一定解释得很糟糕 流=引用类型,指向内存中保存实际对象的位置的指针 参数=作为对象的类型传递(流仍然是引用类型,int将是值类型) Ref Parameter=允许操纵将在方法块外部保留的参数 再看一段时间并运行一些测试,答案似乎取决于我正在尝试做什么。这个问题帮助我区分了我在考试中要做什么: 对于我的大多数助手来说,扩展方法非常有效,因为它们可以返回答案,并且我不需要替换原始对象。对于其他助手,我最好使用带有ref参数的方法,以便更新原始对象。我可以通过返回

更新: 我确实理解基本的C#概念,我一定解释得很糟糕

=引用类型,指向内存中保存实际对象的位置的指针

参数=作为对象的类型传递(流仍然是引用类型,int将是值类型)

Ref Parameter=允许操纵将在方法块外部保留的参数

再看一段时间并运行一些测试,答案似乎取决于我正在尝试做什么。这个问题帮助我区分了我在考试中要做什么:

对于我的大多数助手来说,扩展方法非常有效,因为它们可以返回答案,并且我不需要替换原始对象。对于其他助手,我最好使用带有ref参数的方法,以便更新原始对象。我可以通过返回一个新对象使扩展模拟ref参数,但是这样做是额外分配的内存损失


考虑到我创建的一些助手类,我想知道扩展和带有ref参数的方法之间是否存在功能或性能差异。特别是对于像流这样的大型对象,我的第一个想法是,当在所述流上运行不同的验证时,通过ref传递流会更有效,但是扩展方法也有一个类似于引用的签名,因为它们是静态的

static bool IsValidSize(this Stream stream, long size)

bool IsValidSize(ref Stream stream, long size)
那么这两个方法签名之间是否存在功能或性能差异?

在本例中:

bool IsValidSize(ref Stream stream, long size)
您不会通过
ref
传递
stream
,除非您打算让
IsValidSize
修改调用者使用的流

关于扩展方法,它们的好处是您不需要使用大量的“助手”类。相反,这些方法似乎是它们扩展的类的一部分。这样你就可以说:

stream.IsValidSize(size);
而不是:

StreamHelper.IsValidSize(stream, size);
当你说:

通过ref传递流将更有效


我认为您不太了解C#中的值类型和引用类型之间的区别
stream
是一种引用类型,因此当它被传递给另一个函数时,如果不是由流生成的,那么它将是一个副本。相反,调用者和被调用者都指向(即引用)相同的
实例。这意味着传递引用类型是非常快速和轻量级的。值类型是不同的,因为无论何时分配或传递到函数中,都会创建一个副本。

扩展方法允许您将方法添加到已存在的类中,而无需访问源代码

按引用传递和扩展方法不相关

扩展方法和带有ref参数的方法之间有什么区别

你怎么称呼它,区别是这样的

public static void ConcatExtension(this string s, string strToAppend) {
    s = s + strToAppend;
}
// ... sometime later
string str = "this is ";
str.ConcatExtension("my string");
这与带有ref参数的静态方法不同

public static void ConcatStatic(ref string s, string strToAppend) {
    s = s + strToAppend;
}
// ... sometime later
string str = "this is ";
ConcatStatic(str, "my string");
就功能而言,在本例中是相同的。但是,使用
ref
参数,您可以更改它引用的内容,而使用扩展方法,您无法更改
参数指向的内容

就拿这个例子来说

public static void StringBecomesFoo(ref string s) {
    s = "Foo";
}

// ...
var myStr = "something";
Console.WriteLine(myStr);  // outputs "something"
StringBecomesFoo(ref myStr);
Console.WriteLine(myStr);  // outputs "Foo"

This
替换
ref
是不可能的。这是另一个区别。

但您不会将蒸汽传递给蒸汽扩展方法。我认为你需要查看每一个项目的文档。这个问题没有任何意义;我认为您不理解ref参数是什么。“ref parameter=允许操纵将在方法块之外持久存在的参数”-这实际上是您可以对任何引用类型对象执行的操作,无论是否使用
ref
关键字。如果参数是值类型,则说明是您获得的功能。如果它是一个引用类型,它将是一个对对象引用的引用,这比你的问题要微妙得多。好吧,在这个例子中,通过ref传递是愚蠢的,但是假设这个方法被称为“TrimEndBytes”,那么通过ref传递流会比执行相同操作的扩展更有效吗?我知道引用类型是通过值传递的,值就是对象()的位置的值。从功能上看,这两个签名之间似乎没有区别,我只是想知道是否有人知道有区别,因为它们都使用不同的实现执行相同的操作。我不认为您理解通过ref传递与引用类型或值类型无关。请参阅文档