如果我将流作为传递值类型参数方法传递给方法,我需要将流(c#)重置回开始吗?
本文关键字:方法 开始 类型参数 如果 | 更新日期: 2023-09-27 17:52:16
我在网上看到过几个例子,我必须通过
重置流stream.Seek(0, SeekOrigin.Begin);
但是,如果我将流作为
传递给方法public static bool ValidateStreamLine(Stream stream)
我还需要重置流吗?
请理解,通常情况下,如果我传入int, string, float或任何其他通用变量类型
public static bool ValidateInt(int i)
int I的值不会改变。
传递值方法对流的反应有什么本质上的不同吗?
你似乎误解了c#中参数的传递方式。默认情况下,c#中的所有参数都是通过值传递的。为了通过引用传递它们,您需要使用一个特殊的关键字:ref
或out
,后者通常在参数用作给定方法的第二个输出时使用。(如int.TryPase
)。
要理解它是如何工作的,请确保您清楚以下内容:
- 变量保存值
类型为值类型的变量的值, 是值类型本身的实例:
int i = 1 // i holds the value 1
类型为引用类型的变量的值不是该类型的实例。该值是该实例所在的内存地址。
string s = "Hello!" // s does not hold "Hello!" it holds a number that points to a place in memory where the string "Hello!" lives.
那么,现在我们清楚了这一点,当你按值传递参数(c#的默认值)时会发生什么?所发生的是,生成变量的副本,并将该副本传递给方法。
如果类型是引用类型,那么真正复制并传递给方法的是存储在变量中的值。那是什么?变量引用的对象所在的内存地址。看到发生了什么了吗?原始变量和复制变量都指向同一个对象:
public class Foo
{
var frobbed = false;
public bool Frobbed { get { return frobbed; } }
public void Frob() { frobbed = true; }
}
void Frob(Foo foo) { foo.Frob(); }
var myFoo = new Foo();
Frob(myFoo);
Console.WriteLine(myFoo.Frobbed); //Outputs True! Why? Because myFoo and foo both point to the same object! The value of both variables (memory address) is the same!
如果类型是值类型,则值类型的值本身被复制并传递给方法,因此方法无法修改存储在原始变量中的值类型。
public void Increment(int i) { i = i + 1; }
var myInt = 1;
Increment(myInt);
Console.WriteLine(myInt); //Outputs 1, not 2. Why? i holds its own copy of 1, it knows nothing about the copy of 1 stored in myInt.
当你通过引用传递参数时,情况就改变了。现在,传递给方法的参数不是一个副本,而是原始变量本身。一个合乎逻辑的问题随之而来;这实际上改变了引用类型的行为吗?答案是肯定的,相当多:
public void ByValueCall(string s)
{
s = "Goodbye";
}
public void ByReferenceCall(ref string s)
{
s = "Goodbye";
}
var myString = "Hello!";
Console.WriteLine(ByValueCall(myString )); //outputs "Hello!"
Console.WriteLine(ByValueCall(myString )); //outputs "Goodbye!"
此行为也与值类型相同。这里发生了什么?
当按值传递参数时,方法将获得该变量的副本;因此给实参赋一个新值实际上就是给拷贝赋一个新值;调用处的原始变量并不关心你是否改变了它的副本的值,无论是值类型还是引用类型。它会保持原来的值
通过引用传递实参时,传递的不是一个副本,而是变量本身。在这种情况下,给变量赋一个新值将在调用点保持不变。一个典型的例子是下面的交换方法:
public void Swap(ref int a, ref int b)
{
var temp = a;
a = b;
b = temp;
}
var i1 = 1;
var i2 = 2;
Swap(ref i1, ref i2);
var b = i1 == 2; //true
b = i2 == 1; //true
那么在所有这些之后,你应该明白为什么下面的行为是这样的:
public ResetStream(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
}
var myStream = new ...
myStream.Read(bytes, 0, 1024);
ResetStream(myStream);
var isAtOrigin = myStream.Position == 0; //Returns true!