如果我将流作为传递值类型参数方法传递到方法中,是否需要将流(C#)重置回起始位置
我在互联网上看到过几个例子,上面说我必须通过如果我将流作为传递值类型参数方法传递到方法中,是否需要将流(C#)重置回起始位置,c#,C#,我在互联网上看到过几个例子,上面说我必须通过 stream.Seek(0, SeekOrigin.Begin); 但是,如果我将流作为 public static bool ValidateStreamLine(Stream stream) 我还需要重置流吗 请理解,在通常情况下,如果我将int、string、float或任何其他通用变量类型作为 public static bool ValidateInt(int i) int i的值不会改变 在方法对流的反应上,按值传递方法的性质会有什
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
)
这里需要理解的重要一点是,如果参数的类型是引用类型或值类型,则通过值传递的参数的行为非常不同。这就是你似乎感到困惑的地方
要了解其工作原理,请确保您清楚以下几点:
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!"
这种行为也与值类型相同。这里发生了什么
当您通过值传递参数时,该方法将获得变量的副本;因此,给参数赋值实际上就是给副本赋值;callsite的原始变量不关心更改其副本的值,无论是值类型还是引用类型。它将保持它一直拥有的价值
通过引用传递参数时,不是传递副本,而是传递变量本身。在这种情况下,为变量分配一个新值将在调用站点保持。以下交换方法是一个典型示例:
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!
对流是访问方法,而不是内容。无论如何,你不能通过值传递它,它是一个引用type@PanagiotisKanavos这是否意味着我可以在ValidateStreamLine方法中重置,它也可以工作?@PanagiotisKanavos我很挑剔,但它是按值传递的,它是按值传递的引用类型这个问题没有通用的答案。除了某些流无法重置之外,您还需要阅读任何接受
流
参数的方法的文档,以确定它的要求和期望是什么。@PanagiotisKanavos您的意思是,不能按值传递它?当然可以,这是在C#中传递任何参数的默认方式。类型是引用类型或值类型与如何在C#中传递参数完全无关。@BenKnoble Lol,我完全忘记了这一点。修正了,谢谢。谢谢你的解释:)还有一个问题。除了stream、string类型之外,还有哪些行为类似的类型?有完整的列表吗?@SimonLoh绝大多数都是引用类型。规则很简单:结构是值类型,类是引用类型。如果不确定,只需检查类型的定义即可。
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!