함수에 의해 수정 될 수 있도록 객체를 전달해야하는 함수를 만들고 있습니다. 차이점은 무엇입니까?
public void myFunction(ref MyClass someClass)
과
public void myFunction(out MyClass someClass)
어느 것을 사용해야하며 왜 그런가요?
함수에 의해 수정 될 수 있도록 객체를 전달해야하는 함수를 만들고 있습니다. 차이점은 무엇입니까?
public void myFunction(ref MyClass someClass)
과
public void myFunction(out MyClass someClass)
어느 것을 사용해야하며 왜 그런가요?
답변:
ref
함수에 들어가기 전에 객체가 초기화 out
되었음을 컴파일러에 알리고 함수 내부에서 객체가 초기화 될 것을 컴파일러에 지시합니다.
동안은 그래서 ref
두 가지 방법 인, out
아웃 전용입니다.
ref
수정 수단 :
out
수정 수단 :
out
하면 메소드가 호출되기 전에 초기화 된 경우 해당 메소드에 의해 설정되기 전에 메소드 내에서 전혀 읽을 수 있습니까? 내 말은, 호출 된 메소드가 호출 메소드가 인수로 전달한 것을 읽을 수 있습니까?
Dom이 Peter의 칸막이에 TPS 보고서에 대한 메모에 대해 등장한다고 가정 해 봅시다.
Dom이 심판 주장이라면, 그는 메모 사본을 인쇄했을 것입니다.
Dom이 논쟁의 여지가 없다면, Peter는 그와 함께 가져갈 메모의 새 사본을 인쇄하게 할 것입니다.
나는 설명을 위해 내 손을 시험해 볼 것이다.
가치 유형이 올바르게 작동하는 방식을 이해하고 있다고 생각합니까? 값 유형은 (int, long, struct 등)입니다. ref 명령없이 함수로 보내면 데이터가 복사 됩니다 . 함수에서 해당 데이터에 대한 모든 작업은 원본이 아닌 사본에만 영향을 미칩니다. ref 명령은 ACTUAL 데이터를 보내고 변경 사항은 함수 외부의 데이터에 영향을줍니다.
혼란스러운 부분, 참조 유형을 확인하십시오.
참조 유형을 만들 수 있습니다.
List<string> someobject = new List<string>()
someobject 를 새로 만들면 두 부분이 생성됩니다.
이제 당신이 ref없이 메소드 에 어떤 객체 를 보낼 때 데이터가 아닌 참조 포인터를 복사합니다 . 이제 당신은 이것을 가지고 있습니다 :
(outside method) reference1 => someobject
(inside method) reference2 => someobject
동일한 객체를 가리키는 두 개의 참조 reference2를 사용하여 일부 객체 의 속성을 수정하면 reference1이 가리키는 동일한 데이터에 영향을 미칩니다.
(inside method) reference2.Add("SomeString");
(outside method) reference1[0] == "SomeString" //this is true
reference2를 널 아웃하거나 새 데이터를 가리키면 reference1 또는 data1이 가리키는 데이터에 영향을 미치지 않습니다.
(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true
The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject
이제 객체 에 대한 참조로 메소드 를 보내면 어떻게됩니까 ? 실제 기준 에 SomeObject의이 방법에 보내지. 따라서 이제 데이터에 대한 참조가 하나만 있습니다.
(outside method) reference1 => someobject;
(inside method) reference1 => someobject;
그러나 이것은 무엇을 의미합니까? 그것은 두 가지 주요한 것을 제외하고 ref가 아닌 객체를 보내는 것과 정확히 동일하게 작동합니다.
1) 메소드 내부의 참조를 무효화하면 메소드 외부의 참조를 무효화합니다.
(inside method) reference1 = null;
(outside method) reference1 == null; //true
2) 이제 완전히 다른 데이터 위치를 가리키는 참조를 지정할 수 있으며 함수 외부의 참조는 이제 새 데이터 위치를 가리 킵니다.
(inside method) reference1 = new List<string>();
(outside method) reference1.Count == 0; //this is true
ref
과 out
매개 변수를.
out
키워드 와 동일하게 설명 할 수 있습니까?
심판에 와 아웃 .
out
요구 사항에 적합한 곳이면 어디에서나 사용 하십시오.
C #에서 메서드는 하나의 값만 반환 할 수 있습니다. 둘 이상의 값을 반환하려면 out 키워드를 사용할 수 있습니다. 출력 수정자는 참조 기준으로 반환됩니다. 가장 간단한 대답은 키워드 "out"을 사용하여 메소드에서 값을 얻는 것입니다.
C #에서는 int, float, double 등과 같은 값 형식을 메서드 매개 변수의 인수로 전달하면 값으로 전달됩니다. 따라서 매개 변수 값을 수정하면 메소드 호출의 인수에 영향을 미치지 않습니다. 그러나“ref”키워드로 매개 변수를 표시하면 실제 변수에 반영됩니다.
개 확장, 고양이 예. ref가있는 두 번째 메소드는 호출자가 참조하는 오브젝트를 변경합니다. 따라서 "고양이"!!!
public static void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
Bar(ref myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public static void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
public static void Bar(ref MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
참조 유형 (클래스)을 전달하기 ref
때문에 기본적으로 실제 객체에 대한 참조 만 전달되므로 항상 참조 뒤의 객체를 변경 하기 때문에 사용할 필요가 없습니다 .
예:
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public void Bar(MyClass someObject)
{
someObject.Name = "Cat";
}
클래스를 전달하는 한 ref
메소드 내에서 객체를 변경하려는 경우 사용할 필요가 없습니다 .
someObject = null
하는 Bar
실행 종료. Bar
인스턴스에 대한 참조 만 null 이므로 코드가 제대로 실행됩니다 . 이제 변경 Bar
을 Bar(ref MyClass someObject)
다시 실행 - 당신이를 얻을 수 있습니다 NullReferenceException
때문에 Foo
인스턴스에의 참조가 너무으로 널되었습니다.
예를 들어 (나 같은) 배우는 사람들을 위해 Anthony Kolesov의 말이 있습니다.
요점을 설명하기 위해 ref, out 등의 최소한의 예제를 만들었습니다. 모범 사례를 다루지 않고 차이점을 이해하기위한 예만 다루고 있습니다.
"빵 굽는 사람"
첫 번째는 문자열 참조가 "Baker"를 가리 키도록 변경하기 때문입니다. ref 키워드를 통해 참조를 전달했기 때문에 참조를 변경할 수 있습니다 (=> 문자열에 대한 참조). 두 번째 호출은 문자열에 대한 참조 사본을 가져옵니다.
문자열은 처음에는 특별한 것으로 보입니다. 그러나 문자열은 단지 참조 클래스이며 정의하면
string s = "Able";
s는 텍스트 "Able"을 포함하는 문자열 클래스에 대한 참조입니다! 같은 변수에 대한 또 다른 할당
s = "Baker";
원래 문자열을 변경하지 않고 새 인스턴스를 만들고 해당 인스턴스를 가리켜 봅시다!
다음과 같은 작은 코드 예제로 시도해 볼 수 있습니다.
string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);
당신은 무엇을 기대합니까? s2가 원래 인스턴스를 가리키는 동안 s의 참조를 다른 인스턴스로 설정하기 때문에 여전히 "Able"이됩니다.
편집 : 문자열도 변경할 수 없으므로 기존 문자열 인스턴스를 수정하는 메서드 또는 속성이 없습니다 (문서에서 찾을 수는 있지만 :-)는 찾지 않습니다). 모든 문자열 조작 방법은 새로운 문자열 인스턴스를 반환합니다! (그래서 StringBuilder 클래스를 사용할 때 종종 더 나은 성능을 얻는 이유)
Out : 함수에서 하나의 값만 반환하기 위해 return 문을 사용할 수 있습니다. 그러나 출력 매개 변수를 사용하면 함수에서 두 개의 값을 리턴 할 수 있습니다. 출력 매개 변수는 데이터를 메소드가 아닌 메소드 외부로 전송한다는 점을 제외하고는 참조 매개 변수와 같습니다.
다음 예제는이를 보여줍니다.
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void getValue(out int x )
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* local variable definition */
int a = 100;
Console.WriteLine("Before method call, value of a : {0}", a);
/* calling a function to get the value */
n.getValue(out a);
Console.WriteLine("After method call, value of a : {0}", a);
Console.ReadLine();
}
}
}
ref : 참조 매개 변수는 변수의 메모리 위치에 대한 참조입니다. 값 매개 변수와 달리 참조로 매개 변수를 전달하면이 매개 변수에 대해 새 스토리지 위치가 작성되지 않습니다. 참조 매개 변수는 메소드에 제공되는 실제 매개 변수와 동일한 메모리 위치를 나타냅니다.
C #에서는 ref 키워드를 사용하여 참조 매개 변수를 선언합니다. 다음 예제는이를 보여줍니다.
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void swap(ref int x, ref int y)
{
int temp;
temp = x; /* save the value of x */
x = y; /* put y into x */
y = temp; /* put temp into y */
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* local variable definition */
int a = 100;
int b = 200;
Console.WriteLine("Before swap, value of a : {0}", a);
Console.WriteLine("Before swap, value of b : {0}", b);
/* calling a function to swap the values */
n.swap(ref a, ref b);
Console.WriteLine("After swap, value of a : {0}", a);
Console.WriteLine("After swap, value of b : {0}", b);
Console.ReadLine();
}
}
}
ref 및 out은 C ++에서와 같이 참조를 전달하고 포인터를 전달하는 것처럼 작동합니다.
심판의 경우, 인수를 선언하고 초기화해야합니다.
밖으로, 인수는 선언해야하지만 초기화되거나 초기화되지 않을 수 있습니다
double nbr = 6; // if not initialized we get error
double dd = doit.square(ref nbr);
double Half_nbr ; // fine as passed by out, but inside the calling method you initialize it
doit.math_routines(nbr, out Half_nbr);
out double Half_nbr
..
제작 시간 :
(1) 우리는 호출 방법을 만듭니다 Main()
(2) List 객체 (참조 형 객체)를 생성하여 변수에 저장합니다 myList
.
public sealed class Program
{
public static Main()
{
List<int> myList = new List<int>();
런타임 중 :
(3) 런타임은 주소를 저장하기에 충분히 넓은 # 00에서 스택에 메모리를 할당합니다 ( myList
변수 이름은 실제로 메모리 위치의 별명이기 때문에 # 00 = )
(4) 런타임은 메모리 위치 #FF에서 힙에 목록 객체를 생성합니다 (이 모든 주소는 예를 들어 술입니다)
(5) 런타임은 # 00에 객체의 시작 주소 #FF를 저장합니다 (즉, List 객체의 참조를 포인터에 저장합니다 myList
)
제작 시간으로 돌아 가기 :
(6) 그런 다음 List 객체를 myParamList
호출 된 메서드에 인수로 전달 modifyMyList
하고 새 List 객체를 할당합니다.
List<int> myList = new List<int>();
List<int> newList = ModifyMyList(myList)
public List<int> ModifyMyList(List<int> myParamList){
myParamList = new List<int>();
return myParamList;
}
런타임 중 :
(7) 런타임은 호출 된 메소드의 호출 루틴을 시작하고 그 일부로 매개 변수 유형을 확인합니다.
(8) 참조 유형을 찾으면 매개 변수 variable의 별칭을 지정하기 위해 # 04에서 스택에 메모리를 할당합니다 myParamList
.
(9) 그런 다음 #FF 값도 저장합니다.
(10) 런타임은 메모리 위치 # 004에서 힙에 목록 객체를 만들고 # 04의 #FF를이 값으로 바꿉니다 (또는 원래 List 객체를 역 참조하고이 방법에서 새 List 객체를 가리킴)
# 00의 주소는 변경되지 않으며 #FF에 대한 참조를 유지합니다 (또는 원래 myList
포인터가 방해받지 않음).
심판 키워드는 메소드 파라미터위한 힙 할당 없을 것이다 수단 (8) 및 (9)에 대한 실행 코드의 생성을 스킵하도록 컴파일러에 지시한다. 원래 # 00 포인터를 사용하여 #FF에서 개체를 조작합니다. 원래 포인터가 초기화되지 않으면 런타임이 변수가 초기화되지 않아 진행할 수 없다는 불평을 중단합니다.
아웃 키워드는 꽤 많이 (9)와 (10)에 약간의 수정과 심판과 동일한 컴파일러 지시문입니다. 컴파일러는 인수가 초기화되지 않을 것으로 예상하고 (8), (4) 및 (5)로 계속해서 힙에 객체를 만들고 시작 변수를 인수 변수에 저장합니다. 초기화되지 않은 오류는 발생하지 않으며 저장된 이전 참조는 손실됩니다.
또한 다른 사람의 변수를 클래스의 다른 인스턴스에 재 할당하고 여러 값 등을 반환 하거나 다른 사람이 필요한 것을 사용 ref
하거나 out
다른 사람에게 제공하는 변수로 무엇을 할 것인지 알려줍니다.
당신 은 필요하지 않습니다 ref
또는 out
당신이 할거야 모두 수정 일 경우 내부MyClass
인수에 전달되는 경우 someClass
.
someClass.Message = "Hello World"
당신이 사용하지 여부 ref
, out
또는 아무것도someClass = new MyClass()
내부 쓰기myFunction(someClass)
메소드 someClass
의 범위 myFunction
에서만 보이는 객체가 교체 됩니다. 호출 메소드는 여전히 MyClass
작성하여 메소드에 전달한 원래 인스턴스 에 대해 알고 있습니다.당신 필요 ref
하거나 out
당신이 교환에 계획하는 경우에 someClass
호출하는 방법을 완전히 새로운 개체에 대한 아웃하고 원하는 변경 사항을 확인하려면
someClass = new MyClass()
내부를myFunction(out someClass)
호출 한 메소드에 의해 표시된 객체가 변경됩니다myFunction
그리고 그들은 당신이 그들의 데이터로 무엇을할지 알고 싶어합니다. 수백만 명의 개발자가 사용할 라이브러리를 작성한다고 가정하십시오. 그들이 메소드를 호출 할 때 변수로 무엇을할지 알고 싶어합니다.
사용 ref
하면 "메서드를 호출 할 때 어떤 값에 할당 된 변수를 전달합니다. 내 메소드를 수행하는 동안 다른 것으로 변경 될 수 있다는 점에 유의하십시오. 변수가 이전 오브젝트를 가리키는 것으로 기대하지 마십시오. 내가 끝나면 "
를 사용 out
하면 "내 메소드에 자리 표시 자 변수를 전달합니다. 값이 있는지 여부는 중요하지 않습니다. 컴파일러에서 강제로 새 값을 지정하도록합니다. 내 메소드를 호출하기 전에 변수, 것 내가 다 했어 시간에 따라 다를 수
in
수정 자도 있습니다.그리고 메소드가 전달 된 인스턴스를 다른 인스턴스로 교체하지 못하게합니다. 수백만 명의 개발자에게 "원본 변수 참조를 전달하면 신중하게 제작 된 데이터를 다른 것으로 바꾸지 않겠다고 약속합니다"라고 생각하십시오. in
일부 특이 사항이 있으며 일부 경우에 귀하의 단편과 호환되도록 암시 적 변환이 필요할 수 있습니다.in int
컴파일러 일시적으로 int를 만들고 짧게 확장하여 참조로 전달하고 마무리합니다. 당신이 그것을 망치지 않을 것이라고 선언했기 때문에이 작업을 수행 할 수 있습니다.
Microsoft는 .TryParse
숫자 유형에 대한 방법으로이를 수행했습니다.
int i = 98234957;
bool success = int.TryParse("123", out i);
out
여기에 적극적으로 선언 할 때 매개 변수에 플래그를 지정하여 " 분명히 다른 것을 위해 98234957의 당신의 노력으로 만들어진 가치를 바꿀 것입니다"
물론, 파싱 방법이 다른 것의 값 유형을 바꾸는 것이 허용되지 않는다면 가치 유형을 구문 분석하는 것과 같은 것들에 대해서는 다소 필요합니다. 만들고있는 라이브러리 :
public void PoorlyNamedMethod(out SomeClass x)
당신은 그것이 인 out
것을 알 수 있습니다. 따라서 숫자를 처리하는 데 몇 시간을 보내면 완벽한 SomeClass를 만듭니다.
SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);
글쎄요, 그 시간을 낭비해서 완벽한 수업을하는데 확실히 던져지고 PoorlyNamedMethod로 대체 될 것입니다.
많은 훌륭한 설명을 설명하기 위해 다음 콘솔 앱을 개발했습니다.
using System;
using System.Collections.Generic;
namespace CSharpDemos
{
class Program
{
static void Main(string[] args)
{
List<string> StringList = new List<string> { "Hello" };
List<string> StringListRef = new List<string> { "Hallo" };
AppendWorld(StringList);
Console.WriteLine(StringList[0] + StringList[1]);
HalloWelt(ref StringListRef);
Console.WriteLine(StringListRef[0] + StringListRef[1]);
CiaoMondo(out List<string> StringListOut);
Console.WriteLine(StringListOut[0] + StringListOut[1]);
}
static void AppendWorld(List<string> LiStri)
{
LiStri.Add(" World!");
LiStri = new List<string> { "¡Hola", " Mundo!" };
Console.WriteLine(LiStri[0] + LiStri[1]);
}
static void HalloWelt(ref List<string> LiStriRef)
{ LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }
static void CiaoMondo(out List<string> LiStriOut)
{ LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
}
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
AppendWorld
: StringList
명명 된 사본 LiStri
이 전달됩니다. 메소드 시작시이 사본은 원래 목록을 참조하므로이 목록을 수정하는 데 사용할 수 있습니다. 나중에 메서드 내에서 원래 목록에 영향을 미치지 않는 LiStri
다른 List<string>
개체를 참조 합니다.
HalloWelt
: LiStriRef
이미 초기화 된 별칭입니다
ListStringRef
. 전달 된 List<string>
객체는 새로운 객체를 초기화하는 데 사용되므로 ref
필요했습니다.
CiaoMondo
: LiStriOut
의 별칭이며 ListStringOut
초기화해야합니다.
따라서 메소드가 전달 된 변수가 참조하는 객체를 수정하는 경우 컴파일러에서 사용할 out
수 ref
없으며 컴파일러가 아니라 코드 판독기를 혼동 하기 때문에 사용해서는 안됩니다 . 메소드가 전달 된 인수를 다른 오브젝트를 참조하게하려면 ref
이미 초기화 된 오브젝트 및 out
전달 된 인수의 새 오브젝트를 초기화해야하는 메소드에 사용하십시오. 게다가, ref
과 out
동일하게 동작.
아래에서는 Ref 와 out 을 모두 사용하는 예를 보여 주었습니다 . 이제, 당신은 심판과 외출에 대해 지워질 것입니다.
아래에 언급 된 예제에서 // myRefObj = new myClass {Name = "ref outside called !!"}; 줄에 "할당되지 않은 로컬 변수 'myRefObj'사용"이라는 오류가 표시되지만 out에 해당 오류가 없습니다 .
Ref 사용 위치 : in 매개 변수 를 사용 하여 프로 시저를 호출 할 때 동일한 매개 변수가 해당 proc의 출력을 저장하는 데 사용됩니다.
사용 위치 : in 매개 변수없이 프로 시저를 호출 할 때 동일한 매개 변수가 해당 proc에서 값을 리턴하는 데 사용됩니다. 출력에 주목
public partial class refAndOutUse : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
myClass myRefObj;
myRefObj = new myClass { Name = "ref outside called!! <br/>" };
myRefFunction(ref myRefObj);
Response.Write(myRefObj.Name); //ref inside function
myClass myOutObj;
myOutFunction(out myOutObj);
Response.Write(myOutObj.Name); //out inside function
}
void myRefFunction(ref myClass refObj)
{
refObj.Name = "ref inside function <br/>";
Response.Write(refObj.Name); //ref inside function
}
void myOutFunction(out myClass outObj)
{
outObj = new myClass { Name = "out inside function <br/>" };
Response.Write(outObj.Name); //out inside function
}
}
public class myClass
{
public string Name { get; set; }
}
public static void Main(string[] args)
{
//int a=10;
//change(ref a);
//Console.WriteLine(a);
// Console.Read();
int b;
change2(out b);
Console.WriteLine(b);
Console.Read();
}
// static void change(ref int a)
//{
// a = 20;
//}
static void change2(out int b)
{
b = 20;
}
이 코드를 확인하면 "ref"를 사용할 때의 완전한 차이점을 설명 할 수 있습니다. 그 의미는 이미 int / string을 초기화한다는 의미입니다.
그러나 "out"을 사용할 때 두 조건 모두에서 작동합니다. 위의 u는 int / string을 초기화합니다. 그러나 u는 해당 함수에서 int / string을 초기화해야합니다.
Ref : ref 키워드는 인수를 참조로 전달하는 데 사용됩니다. 이는 메소드에서 해당 매개 변수의 값이 변경되면 호출 메소드에 반영됨을 의미합니다. ref 키워드를 사용하여 전달 된 인수는 호출 된 메소드로 전달되기 전에 호출 메소드에서 초기화되어야합니다.
Out : out 키워드는 ref 키워드와 같은 인수를 전달하는 데에도 사용되지만 값을 지정하지 않고 인수를 전달할 수 있습니다. out 키워드를 사용하여 전달 된 인수는 호출 된 메소드로 돌아 가기 전에 호출 된 메소드에서 초기화되어야합니다.
public class Example
{
public static void Main()
{
int val1 = 0; //must be initialized
int val2; //optional
Example1(ref val1);
Console.WriteLine(val1);
Example2(out val2);
Console.WriteLine(val2);
}
static void Example1(ref int value)
{
value = 1;
}
static void Example2(out int value)
{
value = 2;
}
}
/* Output 1 2
메서드 오버로딩에서 참조 및 출력
ref와 out은 동시에 메소드 오버로드에 사용될 수 없습니다. 그러나 ref와 out은 런타임에 다르게 처리되지만 컴파일 타임에 동일하게 처리됩니다 (ref 및 out에 대한 IL을 생성하는 동안 CLR은 둘을 구분하지 않습니다).
파라미터의 차이를 수신하는 방법의 관점에서 ref
그리고 out
그 C #을하는 방법은 매에 기록해야 필요 out
돌아 가기 전에 변수, 및로 전달하는 대신, 이러한 매개 변수와 다른 아무것도하지해야 out
파라미터 또는 서면 out
다른 메소드에 매개 변수로 전달 되거나 직접 작성 될 때까지 . 일부 다른 언어는 그러한 요구 사항을 강요하지 않습니다. C #에서 out
매개 변수로 선언 된 가상 또는 인터페이스 메서드 는 다른 매개 변수로 재정의 될 수 있으며 이러한 매개 변수에 대한 특별한 제한은 없습니다.
호출자의 관점에서 C #은 out
매개 변수를 사용 하여 메서드를 호출 할 때 전달 된 변수가 먼저 읽히지 않고 쓰여질 때 많은 상황을 가정 합니다. 다른 언어로 작성된 메소드를 호출 할 때이 가정이 올바르지 않을 수 있습니다. 예를 들면 다음과 같습니다.
struct MyStruct
{
...
myStruct(IDictionary<int, MyStruct> d)
{
d.TryGetValue(23, out this);
}
}
C # 이외의 언어로 작성된 구현을 myDictionary
식별하는 경우 과제처럼 보이지만 잠재적으로 떠날 수 있습니다.IDictionary<TKey,TValue>
MyStruct s = new MyStruct(myDictionary);
s
수정되지 않은.
VB.NET으로 작성된 생성자는 C #의 생성자와 달리 호출 된 메소드가 out
매개 변수 를 수정하는지 여부에 대한 가정을하지 않으며 모든 필드를 무조건 지 웁니다. 위에서 언급 한 이상한 동작은 VB 또는 C #으로 작성된 코드에서는 발생하지 않지만 C #으로 작성된 코드가 VB.NET으로 작성된 메서드를 호출 할 때 발생할 수 있습니다.
매개 변수를 참조로 전달하려면 매개 변수를 함수에 전달하기 전에 매개 변수를 초기화해야합니다. 그렇지 않으면 컴파일러 자체가 오류를 표시합니다. 그러나 매개 변수가 없으면 매개 변수를 전달하기 전에 개체 매개 변수를 초기화 할 필요가 없습니다. 호출 메소드 자체에서 오브젝트를 초기화 할 수 있습니다.
함수 내부에 전달 된 참조 매개 변수가 직접 처리된다는 점에 유의하십시오.
예를 들어
public class MyClass
{
public string Name { get; set; }
}
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
}
public void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
이것은 고양이가 아니라 개를 쓸 것입니다. 따라서 someObject에서 직접 작업해야합니다.
나는 이것에 익숙하지 않을 수도 있지만 분명히 문자열은 (기술적으로 참조 유형이고 힙에 살고 있지만) 참조가 아닌 값으로 전달됩니까?
string a = "Hello";
string b = "goodbye";
b = a; //attempt to make b point to a, won't work.
a = "testing";
Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!
그렇기 때문에 변경하는 함수의 범위를 벗어나는 변경 사항을 원한다면 참조가 필요합니다. 그렇지 않으면 참조를 전달하지 않습니다.
내가 아는 한 구조체 / 값 유형과 문자열 자체에 대한 참조 만 필요합니다. 문자열은 척하는 참조 유형이지만 값 유형은 아닙니다.
나는 여기서 완전히 틀릴 수 있습니다.
Capitalize()
의 내용을 대문자로 변경 하는 메소드가 있다고 상상해보십시오 . 당신이 다음 라인을 교체 한 경우 a = "testing";
로 a.Capitalize();
, 다음 출력은 "HELLO"가 아닌 "안녕하세요"가 될 것입니다. 불변 유형의 장점 중 하나는 참조를 전달하고 다른 코드가 값을 변경하는 것에 대해 걱정할 수 없다는 것입니다.
MyClass
것class
즉, 참조 형식을 입력합니다. 이 경우 전달하는 객체myFunction
는ref
/out
키워드 없이 짝수 로 수정할 수 있습니다 . 동일한 객체 를 가리키는 새로운 참조를myFunction
수신하고 원하는만큼 동일한 객체를 수정할 수 있습니다. 키워드와 의 차이점은 동일한 객체에 대한 동일한 참조를 받았다는 것 입니다. 다른 객체 를 가리 키도록 참조를 변경하는 경우에만 중요 합니다.ref
myFunction
myFunction