`+ =`에 대한 C # 연산자 과부하?
에 대한 연산자 오버로드를 시도하고 +=
있지만 할 수 없습니다. 에 대한 연산자 오버로드 만 만들 수 있습니다 +
.
어떻게 오세요?
편집하다
이것이 작동하지 않는 이유는 Vector 클래스 (X 및 Y 필드 포함)가 있기 때문입니다. 다음 예를 고려하십시오.
vector1 += vector2;
운영자 과부하가 다음으로 설정된 경우 :
public static Vector operator +(Vector left, Vector right)
{
return new Vector(right.x + left.x, right.y + left.y);
}
그러면 결과가 vector1에 추가되지 않고 대신 vector1이 참조로 새로운 Vector가됩니다.
MSDN의 과부하 연산자 :
할당 연산자는 오버로드 될 수 없지만
+=
예를 들어을 사용하여+
오버로드 될 수있는을 사용하여 평가됩니다 .
또한 할당 연산자 중 어느 것도 오버로드 될 수 없습니다. CLR 강력한 유형 세계에서 잠재적 인 보안 허점 인 가비지 수집 및 메모리 관리에 영향을 미칠 것이기 때문이라고 생각합니다.
그럼에도 불구하고 정확히 연산자가 무엇인지 봅시다. 유명한 Jeffrey Richter의 저서 에 따르면 , 각 프로그래밍 언어에는 고유 한 연산자 목록이 있으며 특수 메소드 호출로 컴파일되며 CLR 자체는 연산자에 대해 아무것도 모릅니다. 따라서 +
and +=
연산자 뒤에 정확히 무엇이 있는지 살펴 보겠습니다 .
이 간단한 코드를 참조하십시오 :
Decimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
이 지침에 대한 IL 코드를 확인하십시오.
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
이제이 코드를 보자 :
Decimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
그리고 이것을위한 IL 코드 :
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
그들은 평등하다! 따라서 +=
연산자는 C # 의 프로그램 에 대한 구문 설탕 일 뿐이며 +
연산자를 단순히 오버로드 할 수 있습니다 .
예를 들면 다음과 같습니다.
class Foo
{
private int c1;
public Foo(int c11)
{
c1 = c11;
}
public static Foo operator +(Foo c1, Foo x)
{
return new Foo(c1.c1 + x.c1);
}
}
static void Main(string[] args)
{
Foo d1 = new Foo (10);
Foo d2 = new Foo(11);
d2 += d1;
}
이 코드는 다음과 같이 컴파일되고 성공적으로 실행됩니다.
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldc.i4.s 11
IL_000b: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: ldloc.0
IL_0013: call class ConsoleApplication2.Program/Foo ConsoleApplication2.Program/Foo::op_Addition(class ConsoleApplication2.Program/Foo,
class ConsoleApplication2.Program/Foo)
IL_0018: stloc.1
최신 정보:
업데이트에 따르면 @EricLippert에서 알 수 있듯이 벡터는 불변 개체로 있어야합니다. 두 벡터를 더한 결과는 크기가 다른 첫 벡터가 아닌 새 벡터입니다.
어떤 이유로 든 첫 번째 벡터를 변경 해야하는 경우이 과부하를 사용할 수 있습니다 (그러나 저에게는 매우 이상한 행동입니다).
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}
나는 당신 이이 링크를 유익하게 찾을 것이라고 생각합니다 : 과부하 연산자
할당 연산자는 오버로드 될 수 없지만 + =는 +를 사용하여 평가되며, 오버로드 될 수 있습니다.
+=
실제로 고유 한 연산자가 아니기 때문에 오버로드 할 수 없으며 구문 설탕 일뿐 입니다. x += y
단지 짧은 쓰기 방법입니다 x = x + y
. 때문에 +=
의 관점에서 정의 +
하고 =
당신이 경우에 문제를 만들 수 별도로 오버라이드 (override) 할 수 있도록 사업자 x += y
와 x = x + y
동일한 방식으로 행동하지 않았다.
하위 수준에서 C # 컴파일러는 두 표현식을 동일한 바이트 코드로 컴파일 할 가능성이 매우 높습니다. 즉, 프로그램 실행 중에 런타임에서 런타임에서 다르게 처리 할 수 없을 가능성이 높습니다 .
나는 당신이 그것을 별도의 연산처럼 취급하고 싶을 수도 있음을 이해할 수 있습니다 : x += 10
당신 과 같은 진술에서 당신은 x
객체를 변경하고 x + 10
이전의 객체 위에 할당하기 전에 새로운 객체 를 생성하는 대신 시간 / 메모리를 절약 할 수 있다는 것을 알고 있습니다 .
그러나이 코드를 고려하십시오 :
a = ...
b = a;
a += 10;
a == b
마지막에 해야합니까 ? 대부분의 유형에서 아니요 a
는 10보다 큽니다 b
. 그러나 +=
연산자를 오버로드하여 변경을 할 수 있다면 가능합니다 . 이제을 고려 a
하고 b
프로그램의 먼 부분에 건네받을 수 있습니다. 코드가 예상하지 않은 곳에서 객체가 변경되기 시작하면 가능한 최적화로 인해 혼란스러운 버그가 발생할 수 있습니다.
다시 말해, 성능이 그렇게 중요한 경우 x += 10
와 같은 메소드 호출 로 대체하기 가 어렵지 않으며 x.increaseBy(10)
관련된 모든 사람에게 훨씬 명확합니다.
이는 할당 연산자가 오버로드 될 수없는 것과 같은 이유 때문입니다. 할당을 올바르게 수행하는 코드를 작성할 수 없습니다.
class Foo
{
// Won't compile.
public static Foo operator= (Foo c1, int x)
{
// duh... what do I do here? I can't change the reference of c1.
}
}
할당 연산자는 오버로드 될 수 없지만 + =는 +를 사용하여 평가되며, 오버로드 될 수 있습니다.
에서 MSDN .
이 연산자는 오버로드 될 수 없기 때문입니다.
할당 연산자는 오버로드 될 수 없지만 + =는 +를 사용하여 평가되며, 오버로드 될 수 있습니다.
+
때문에 과부하 연산자
x += y
동일 x = x + y
에 대한 연산자 과부하 +
가 +=
연산자에서 사용 A += B
됩니다 A = operator+(A, B)
.
다음 +
과 같이 연산자 를 과부하 하면 :
class Foo
{
public static Foo operator + (Foo c1, int x)
{
// implementation
}
}
넌 할 수있어
Foo foo = new Foo();
foo += 10;
또는
foo = foo + 10;
컴파일과 똑같이 실행됩니다.
There is always the same answer to this problem: Why do you need the +=
, if you get it for free if you overload the +
. But what happens if I have a class like this.
using System;
using System.IO;
public class Class1
{
public class MappableObject
{
FileStream stream;
public int Blocks;
public int BlockSize;
public MappableObject(string FileName, int Blocks_in, int BlockSize_in)
{
Blocks = Blocks_in;
BlockSize = BlockSize_in;
// Just create the file here and set the size
stream = new FileStream(FileName); // Here we need more params of course to create a file.
stream.SetLength(sizeof(float) * Blocks * BlockSize);
}
public float[] GetBlock(int BlockNo)
{
long BlockPos = BlockNo * BlockSize;
stream.Position = BlockPos;
using (BinaryReader reader = new BinaryReader(stream))
{
float[] resData = new float[BlockSize];
for (int i = 0; i < BlockSize; i++)
{
// This line is stupid enough for accessing files a lot and the data is large
// Maybe someone has an idea to make this faster? I tried a lot and this is the simplest solution
// for illustration.
resData[i] = reader.ReadSingle();
}
}
retuen resData;
}
public void SetBlock(int BlockNo, float[] data)
{
long BlockPos = BlockNo * BlockSize;
stream.Position = BlockPos;
using (BinaryWriter reader = new BinaryWriter(stream))
{
for (int i = 0; i < BlockSize; i++)
{
// Also this line is stupid enough for accessing files a lot and the data is large
reader.Write(data[i];
}
}
retuen resData;
}
// For adding two MappableObjects
public static MappableObject operator +(MappableObject A, Mappableobject B)
{
// Of course we have to make sure that all dimensions are correct.
MappableObject result = new MappableObject(Path.GetTempFileName(), A.Blocks, A.BlockSize);
for (int i = 0; i < Blocks; i++)
{
float[] dataA = A.GetBlock(i);
float[] dataB = B.GetBlock(i);
float[] C = new float[dataA.Length];
for (int j = 0; j < BlockSize; j++)
{
C[j] = A[j] + B[j];
}
result.SetBlock(i, C);
}
}
// For adding a single float to the whole data.
public static MappableObject operator +(MappableObject A, float B)
{
// Of course we have to make sure that all dimensions are correct.
MappableObject result = new MappableObject(Path.GetTempFileName(), A.Blocks, A.BlockSize);
for (int i = 0; i < Blocks; i++)
{
float[] dataA = A.GetBlock(i);
float[] C = new float[dataA.Length];
for (int j = 0; j < BlockSize; j++)
{
C[j] = A[j] + B;
}
result.SetBlock(i, C);
}
}
// Of course this doesn't work, but maybe you can see the effect here.
// when the += is automimplemented from the definition above I have to create another large
// object which causes a loss of memory and also takes more time because of the operation -> altgough its
// simple in the example, but in reality it's much more complex.
public static MappableObject operator +=(MappableObject A, float B)
{
// Of course we have to make sure that all dimensions are correct.
MappableObject result = new MappableObject(Path.GetTempFileName(), A.Blocks, A.BlockSize);
for (int i = 0; i < Blocks; i++)
{
float[] dataA = A.GetBlock(i);
for (int j = 0; j < BlockSize; j++)
{
A[j]+= + B;
}
result.SetBlock(i, A);
}
}
}
}
Do you still say that it is good that the +=
is "auto-implemented". If you try to do high-performance computing in C# you need to have such features to reduce processing time and memory consumption, if someone has a good solution it is highly appreciated, but don't tell me I have to do this with static methods, this is only a workaround and I see no reason why C# does the +=
implemention if it is not defined, and if it is defined it will be used. Some people say that not having a difference between +
and +=
prevents errors, but isn't this my own problem?
I had the exact same question and i can not possibly answer it better then this person has
A better design method is Explicit Casting. You can definitely overload Casting.
참고URL : https://stackoverflow.com/questions/6587107/c-sharp-operator-overload-for
'program tip' 카테고리의 다른 글
“class”및“id”HTML 속성 이름 지정-대시와 밑줄 (0) | 2020.08.05 |
---|---|
이 대괄호와 괄호 대괄호 표기법은 [first1, last1)을 의미합니까? (0) | 2020.08.05 |
미니멀리스트 예 Haskell quicksort가 "true"quicksort가 아닌 이유는 무엇입니까? (0) | 2020.08.05 |
트위터 부트 스트랩과 jquery-mobile (0) | 2020.08.05 |
힘내 diff-diff 목록을 종료하는 방법 (0) | 2020.08.04 |