키워드 "new"는 C #의 구조체에 어떤 역할을합니까?
C #에서 Structs는 값 측면에서 관리되고 개체는 참조에 있습니다. 내 이해에서 클래스의 인스턴스를 만들 때 키워드 new
는 C #이 클래스 정보를 사용하여 인스턴스를 만들도록합니다.
class MyClass
{
...
}
MyClass mc = new MyClass();
구조체의 경우 객체를 생성하지 않고 단순히 변수를 값으로 설정합니다.
struct MyStruct
{
public string name;
}
MyStruct ms;
//MyStruct ms = new MyStruct();
ms.name = "donkey";
내가 이해하지 못하는 것은 변수를으로 선언하면 여기 MyStruct ms = new MyStruct()
에서 키워드 new
가 명령문에 무엇을 하는가? . 구조체가 객체가 될 수 없다면 new
여기서 인스턴스화 하는 것은 무엇 입니까?
에서 struct (C# Reference)
MSDN에서 :
new 연산자를 사용하여 struct 객체를 생성하면 생성되고 적절한 생성자가 호출됩니다. 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화 할 수 있습니다. new를 사용하지 않는 경우 필드는 할당되지 않은 상태로 유지되며 모든 필드가 초기화 될 때까지 개체를 사용할 수 없습니다.
내 이해에 따르면 모든 필드를 수동으로 초기화하지 않는 한 new 를 사용하지 않고는 실제로 구조체를 제대로 사용할 수 없습니다 . new 연산자를 사용하면 생성자가 자동으로 수행합니다.
그것이 해결되기를 바랍니다. 이에 대한 설명이 필요하면 알려주십시오.
편집하다
주석 스레드가 꽤 길어서 여기에 좀 더 추가 할 생각이었습니다. 나는 그것을 이해하는 가장 좋은 방법은 그것을 시도하는 것이라고 생각합니다. Visual Studio에서 "StructTest"라는 콘솔 프로젝트를 만들고 여기에 다음 코드를 복사합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace struct_test
{
class Program
{
public struct Point
{
public int x, y;
public Point(int x)
{
this.x = x;
this.y = 5;
}
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// It will break with this constructor. If uncommenting this one
// comment out the other one with only one integer, otherwise it
// will fail because you are overloading with duplicate parameter
// types, rather than what I'm trying to demonstrate.
/*public Point(int y)
{
this.y = y;
}*/
}
static void Main(string[] args)
{
// Declare an object:
Point myPoint;
//Point myPoint = new Point(10, 20);
//Point myPoint = new Point(15);
//Point myPoint = new Point();
// Initialize:
// Try not using any constructor but comment out one of these
// and see what happens. (It should fail when you compile it)
myPoint.x = 10;
myPoint.y = 20;
// Display results:
Console.WriteLine("My Point:");
Console.WriteLine("x = {0}, y = {1}", myPoint.x, myPoint.y);
Console.ReadKey(true);
}
}
}
그것으로 놀아 라. 생성자를 제거하고 어떤 일이 발생하는지 확인하십시오. 하나의 변수 만 초기화하는 생성자를 사용해보십시오 (하나를 주석 처리했습니다 ... 컴파일되지 않습니다). 새 키워드를 사용하거나 사용하지 않고 시도하십시오 (몇 가지 예를 주석으로 처리하고 주석을 제거하고 시도해 봅니다).
잡아 이 스레드에서 에릭 Lippert의의 훌륭한 대답을. 그를 인용하려면 :
값 유형을 "새로 작성"하면 세 가지가 발생합니다. 첫째, 메모리 관리자는 단기 저장 공간에서 공간을 할당합니다. 둘째, 생성자는 단기 저장 위치에 대한 참조를 전달합니다. 생성자가 실행 된 후에는 단기 저장 위치에 있던 값이 해당 값의 저장 위치에 복사됩니다. 값 유형의 변수는 실제 값을 저장합니다.
(컴파일러가 부분적으로 구성된 구조체를 사용자 코드에 노출하지 않는다고 컴파일러가 결정할 수있는 경우 컴파일러는이 세 단계를 한 단계로 최적화 할 수 있습니다. 즉, 컴파일러는 최종 참조를 단순히 전달하는 코드를 생성 할 수 있습니다. 생성자에 저장 위치를 할당하여 하나의 할당과 하나의 복사본을 저장합니다.)
( 정말 하나이기 때문에이 대답을 )
"new MyStuct ()"를 사용하면 모든 필드가 특정 값으로 설정됩니다. 위의 경우에는 차이가 없습니다. ms.name을 설정하는 대신 읽을 위치를 지정하는 대신 VS에서 "할당되지 않은 필드 '이름'사용 가능"오류가 발생합니다.
객체 나 구조체가 존재할 때마다 모든 필드도 함께 존재합니다. 이러한 필드 중 하나가 구조체 유형이면 모든 중첩 필드도 존재합니다. 배열이 생성되면 모든 요소가 존재합니다 (위와 같이 해당 요소가 구조체 인 경우 해당 구조체의 필드도 존재합니다). 이 모든 것은 생성자 코드가 실행되기 전에 발생합니다.
.net에서 struct 생성자는 사실상 struct를 'out'매개 변수로 취하는 메소드에 지나지 않습니다. C #에서 구조체 생성자를 호출하는 식은 임시 구조체 인스턴스를 할당하고 생성자를 호출 한 다음 해당 임시 인스턴스를 식의 값으로 사용합니다. 이는 생성자에 대해 생성 된 코드가 모든 필드를 제로화하여 시작되지만 호출자의 코드가 생성자가 대상에서 직접 작동하도록 시도하는 vb.net과는 다릅니다. 예 : myStruct = new myStructType(whatever)
vb.net myStruct
에서는 생성자의 첫 번째 문이 실행되기 전에 지워집니다 . 생성자 내에서 생성중인 객체에 대한 모든 쓰기는에서 즉시 작동합니다 myStruct
.
구조체에서 new
키워드는 불필요하게 혼동됩니다. 아무것도하지 않습니다. 생성자를 사용하려는 경우에만 필요합니다. 그것은 않습니다 하지 을 수행합니다 new
.
의 일반적인 의미는 new
영구 저장을 할당하는 것입니다 (힙에.) C ++와 같은 언어는 허용 new myObject()
하거나 myObject()
. 둘 다 동일한 생성자를 호출합니다. 그러나 전자는 새로운 객체를 생성하고 포인터를 반환합니다. 후자는 단순히 임시를 만듭니다. 모든 구조체 또는 클래스는 둘 중 하나를 사용할 수 있습니다. new
선택이며 의미가 있습니다.
C #은 선택권을주지 않습니다. 클래스는 항상 힙에 있고 구조체는 항상 스택에 있습니다. new
구조체 에서 실제를 수행하는 것은 불가능합니다 . 숙련 된 C # 프로그래머가 이에 익숙합니다. 그들이 볼 때 그들은 as just 구문 ms = new MyStruct();
을 무시하는 것을 알고 new
있습니다. 그들은 ms = MyStruct()
단순히 기존 객체에 할당 하는 것처럼 작동한다는 것을 알고 있습니다 .
이상하게도 (?), 클래스에는 new
. c=myClass();
허용되지 않습니다 (생성자를 사용하여 기존 객체의 값을 설정합니다 c
.) c.init();
. 따라서 선택의 여지가 없습니다. 생성자는 항상 클래스에 할당하고 구조체에는 할당하지 않습니다. 은 new
언제나 장식입니다.
new
구조체에 fake를 요구하는 이유 는 구조체를 클래스로 쉽게 변경할 수 있기 때문이라고 생각합니다 ( myStruct=new myStruct();
처음 선언 할 때 항상 사용한다고 가정하면 권장 됨).
ValueType
구조는 C #에서 특별한 것입니다. 여기 나는 당신이 뭔가 새로운 것을 할 때 일어나는 일을 보여주고 있습니다 .
여기에 다음이 있습니다.
암호
partial class TestClass { public static void NewLong() { var i=new long(); } public static void NewMyLong() { var i=new MyLong(); } public static void NewMyLongWithValue() { var i=new MyLong(1234); } public static void NewThatLong() { var i=new ThatLong(); } } [StructLayout(LayoutKind.Sequential)] public partial struct MyLong { const int bits=8*sizeof(int); public static implicit operator int(MyLong x) { return (int)x.m_Low; } public static implicit operator long(MyLong x) { long y=x.m_Hi; return (y<<bits)|x.m_Low; } public static implicit operator MyLong(long x) { var y=default(MyLong); y.m_Low=(uint)x; y.m_Hi=(int)(x>>bits); return y; } public MyLong(long x) { this=x; } uint m_Low; int m_Hi; } public partial class ThatLong { const int bits=8*sizeof(int); public static implicit operator int(ThatLong x) { return (int)x.m_Low; } public static implicit operator long(ThatLong x) { long y=x.m_Hi; return (y<<bits)|x.m_Low; } public static implicit operator ThatLong(long x) { return new ThatLong(x); } public ThatLong(long x) { this.m_Low=(uint)x; this.m_Hi=(int)(x>>bits); } public ThatLong() { int i=0; var b=i is ValueType; } uint m_Low; int m_Hi; }
그리고 테스트 클래스 메서드의 생성 된 IL은 다음과 같습니다.
IL
// NewLong .method public hidebysig static void NewLong () cil managed { .maxstack 1 .locals init ( [0] int64 i ) IL_0000: nop IL_0001: ldc.i4.0 // push 0 as int IL_0002: conv.i8 // convert the pushed value to long IL_0003: stloc.0 // pop it to the first local variable, that is, i IL_0004: ret } // NewMyLong .method public hidebysig static void NewMyLong () cil managed { .maxstack 1 .locals init ( [0] valuetype MyLong i ) IL_0000: nop IL_0001: ldloca.s i // push address of i IL_0003: initobj MyLong // pop address of i and initialze as MyLong IL_0009: ret } // NewMyLongWithValue .method public hidebysig static void NewMyLongWithValue () cil managed { .maxstack 2 .locals init ( [0] valuetype MyLong i ) IL_0000: nop IL_0001: ldloca.s i // push address of i IL_0003: ldc.i4 1234 // push 1234 as int IL_0008: conv.i8 // convert the pushed value to long // call the constructor IL_0009: call instance void MyLong::.ctor(int64) IL_000e: nop IL_000f: ret } // NewThatLong .method public hidebysig static void NewThatLong () cil managed { // Method begins at RVA 0x33c8 // Code size 8 (0x8) .maxstack 1 .locals init ( [0] class ThatLong i ) IL_0000: nop // new by calling the constructor and push it's reference IL_0001: newobj instance void ThatLong::.ctor() // pop it to the first local variable, that is, i IL_0006: stloc.0 IL_0007: ret }
메서드의 동작은 IL 코드에 주석으로 표시됩니다. 그리고 OpCodes.Initobj 및 OpCodes.Newobj를 살펴볼 수 있습니다. 값 유형은 일반적으로 OpCodes.Initobj로 초기화 되지만 MSDN에서 OpCodes.Newobj 도 사용됩니다.
-
Value types are not usually created using newobj. They are usually allocated either as arguments or local variables, using newarr (for zero-based, one-dimensional arrays), or as fields of objects. Once allocated, they are initialized using Initobj. However, the newobj instruction can be used to create a new instance of a value type on the stack, that can then be passed as an argument, stored in a local, and so on.
For each value type which is numeric, from byte
to double
, has a defined op-code. Although they are declared as struct
, there's some difference in the generated IL as shown.
Here are two more things to mention:
ValueType
itself is declared a abstract classThat is, you cannot new it directly.
struct
s cannot contain explicit parameterless constructorsThat is, when you new a
struct
, you would fall into the case above of eitherNewMyLong
orNewMyLongWithValue
.
To summarize, new for the value types and structures are for the consistency of the language concept.
참고URL : https://stackoverflow.com/questions/9207488/what-does-the-keyword-new-do-to-a-struct-in-c
'developer tip' 카테고리의 다른 글
SignalR에서 특정 클라이언트 호출 (0) | 2020.11.25 |
---|---|
Internet Explorer (9)가 UserAgent에서 "Mozilla"를보고하는 이유는 무엇입니까? (0) | 2020.11.25 |
jQuery .text () 메서드는 XSS 안전합니까? (0) | 2020.11.25 |
Visual Studio에 MySQL 데이터 원본이 나타나지 않음 (0) | 2020.11.25 |
DrawerLayout 이중 서랍 (왼쪽 및 오른쪽 서랍 동시) (0) | 2020.11.25 |