C #에서 필자는 기본이 아닌 변수는 참조로 전달되고 기본 값은 값으로 전달된다고 생각했습니다.
따라서 기본이 아닌 객체를 메소드에 전달할 때 메소드의 객체에 수행 된 모든 작업은 객체가 전달되는 데 영향을 미칩니다. (C # 101 물건)
그러나 System.Drawing.Image 개체를 전달할 때 이것이 그렇지 않은 것으로 나타났습니다. system.drawing.image 객체를 다른 메소드에 전달하고 해당 객체에 이미지를로드 한 다음 해당 메소드가 범위를 벗어나 호출 메소드로 돌아 가면 해당 이미지가 원래 객체에로드되지 않습니까?
왜 이런거야?
답변
객체 는 전혀 전달되지 않습니다. 기본적으로 인수는 평가되고 해당 값 은 호출하는 메서드 매개 변수의 초기 값으로 값별로 전달됩니다. 이제 중요한 점은 값이 참조 유형에 대한 참조-객체에 도달하는 방법 (또는 null)라는 것입니다. 해당 객체의 변경 사항은 발신자에게 표시됩니다. 그러나 다른 유형을 참조하도록 매개 변수 값을 변경하면 모든 유형 의 기본값 인 전달 값을 사용할 때 표시 되지 않습니다 .
당신이 통과하여 참조를 사용하려면 있어야 사용 out
하거나 ref
매개 변수 유형은 값 형식 또는 참조 형식인지. 이 경우 효과적으로 변수 자체가 참조로 전달되므로 매개 변수는 인수와 동일한 저장 위치를 사용하며 매개 변수 자체의 변경 사항은 호출자가 볼 수 있습니다.
그래서:
public void Foo(Image image)
{
// This change won't be seen by the caller: it's changing the value
// of the parameter.
image = Image.FromStream(...);
}
public void Foo(ref Image image)
{
// This change *will* be seen by the caller: it's changing the value
// of the parameter, but we're using pass by reference
image = Image.FromStream(...);
}
public void Foo(Image image)
{
// This change *will* be seen by the caller: it's changing the data
// within the object that the parameter value refers to.
image.RotateFlip(...);
}
나는 이것에 훨씬 더 많은 기사를 가지고있다 . 기본적으로 “참조로 전달”이 의미하는 바를 의미하지는 않습니다.
답변
이것을 보여주는 또 하나의 코드 샘플 :
void Main()
{
int k = 0;
TestPlain(k);
Console.WriteLine("TestPlain:" + k);
TestRef(ref k);
Console.WriteLine("TestRef:" + k);
string t = "test";
TestObjPlain(t);
Console.WriteLine("TestObjPlain:" +t);
TestObjRef(ref t);
Console.WriteLine("TestObjRef:" + t);
}
public static void TestPlain(int i)
{
i = 5;
}
public static void TestRef(ref int i)
{
i = 5;
}
public static void TestObjPlain(string s)
{
s = "TestObjPlain";
}
public static void TestObjRef(ref string s)
{
s = "TestObjRef";
}
그리고 출력 :
TestPlain : 0
TestRef : 5
TestObjPlain : 테스트
TestObjRef : 테스트 ObjRef
답변
좋은 답변이 많이 추가되었습니다. 나는 여전히 공헌하고 싶습니다. 약간 더 명확해질 것입니다.
인스턴스를 메소드에 인수로 전달하면 인스턴스의 인스턴스를 전달합니다 copy
. 이제 전달하는 인스턴스가 value type
( stack
)에 있으면 해당 값 의 사본 을 전달 하므로 수정하면 호출자에게 반영되지 않습니다. 인스턴스가 참조 유형 인 경우 참조 사본 ( stack
)이 객체에 전달됩니다. 따라서 동일한 객체에 대한 두 개의 참조가 있습니다. 둘 다 객체를 수정할 수 있습니다. 그러나 메소드 본문 내에서 새 오브젝트를 인스턴스화하면 참조 사본이 더 이상 원래 오브젝트를 참조하지 않고 방금 작성한 새 오브젝트를 참조합니다. 따라서 2 개의 참조와 2 개의 객체가 생깁니다.
답변
당신이 이렇게하면 더 명확하다고 생각합니다. LinqPad 를 다운로드 하여 이와 같은 것을 테스트하는 것이 좋습니다 .
void Main()
{
var Person = new Person(){FirstName = "Egli", LastName = "Becerra"};
//Will update egli
WontUpdate(Person);
Console.WriteLine("WontUpdate");
Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}\n");
UpdateImplicitly(Person);
Console.WriteLine("UpdateImplicitly");
Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}\n");
UpdateExplicitly(ref Person);
Console.WriteLine("UpdateExplicitly");
Console.WriteLine($"First name: {Person.FirstName}, Last name: {Person.LastName}\n");
}
//Class to test
public class Person{
public string FirstName {get; set;}
public string LastName {get; set;}
public string printName(){
return $"First name: {FirstName} Last name:{LastName}";
}
}
public static void WontUpdate(Person p)
{
//New instance does jack...
var newP = new Person(){FirstName = p.FirstName, LastName = p.LastName};
newP.FirstName = "Favio";
newP.LastName = "Becerra";
}
public static void UpdateImplicitly(Person p)
{
//Passing by reference implicitly
p.FirstName = "Favio";
p.LastName = "Becerra";
}
public static void UpdateExplicitly(ref Person p)
{
//Again passing by reference explicitly (reduntant)
p.FirstName = "Favio";
p.LastName = "Becerra";
}
그리고 그것은 출력되어야합니다
WontUpdate
이름 : Egli, 성 : Becerra
암시 적으로 업데이트
이름 : Favio, 성 : Becerra
명시 적으로 업데이트
이름 : Favio, 성 : Becerra
답변
당신이 통과 할 때 System.Drawing.Image
하는 방법에 유형의 객체를 실제로 객체 참조의 사본을 전달한다.
따라서 해당 방법 내에서 새 이미지를로드하는 경우 새 / 복사 된 참조를 사용하여로드하는 것입니다. 원본을 변경하지 않았습니다.
YourMethod(System.Drawing.Image image)
{
//now this image is a new reference
//if you load a new image
image = new Image()..
//you are not changing the original reference you are just changing the copy of original reference
}
답변
어떻게 객체를 메소드에 전달 했습니까?
객체의 해당 메소드에서 새로운 작업을하고 있습니까? 그렇다면 ref
방법 을 사용해야 합니다.
다음 링크는 더 나은 아이디어를 제공합니다.
http://dotnetstep.blogspot.com/2008/09/passing-reference-type-byval-or-byref.html
답변
Pass By Reference에서 함수 매개 변수에는 “ref”만 추가하고 main 때문에 static (# public void main(String[] args)
) 때문에 함수 “static”을 선언해야하는 것이 한 가지 더 있습니다 !
namespace preparation
{
public class Program
{
public static void swap(ref int lhs,ref int rhs)
{
int temp = lhs;
lhs = rhs;
rhs = temp;
}
static void Main(string[] args)
{
int a = 10;
int b = 80;
Console.WriteLine("a is before sort " + a);
Console.WriteLine("b is before sort " + b);
swap(ref a, ref b);
Console.WriteLine("");
Console.WriteLine("a is after sort " + a);
Console.WriteLine("b is after sort " + b);
}
}
}