AKTUALIZACJA: Znalazłem odpowiedź, którą opublikuję za kilka dni, jeśli nikt inny tego nie zrobi.Przeciążanie operatora + tak, że jest on wrażliwy na wywoływanie w zaznaczonym lub niezaznaczonym kontekście
Tworzę strukturę numeryczną, więc przeciążam operatory arytmetyczne. Oto przykład do struktury, która reprezentuje 4-bitowego liczbę całkowitą bez znaku:
public struct UInt4
{
private readonly byte _value;
private const byte MinValue = 0;
private const byte MaxValue = 15;
public UInt4(int value)
{
if (value < MinValue || value > MaxValue)
throw new ArgumentOutOfRangeException("value");
_value = (byte) value;
}
public static UInt4 operator +(UInt4 a, UInt4 b)
{
return new UInt4((a._value + b._value) & MaxValue);
}
}
przeciążone operator dodawania pozwala to kod:
var x = new UInt4(10);
var y = new UInt4(11);
var z = x + y;
tu przepełnienia obliczeń, tak zmienna z ma wartość 5
. Chciałbym również móc to zrobić:
var x = new UInt4(10);
var y = new UInt4(11);
var z = checked (x + y);
Ta próbka powinna wywołać wyjątek OverflowException. Jak mogę to osiągnąć?
już ustalone, że sprawdzone kontekst nie obejmuje zwanych metod, tak, na przykład, nie rzucać, niezależnie od tego, czy to się nazywa w kratkę lub nierejestrowanego kontekstu:
public static UInt4 operator +(UInt4 a, UInt4 b)
{
int i = int.MaxValue;
//this should throw in a checked context, but when
//the operator is used in a checked context, this statement
//is nonetheless unchecked.
byte b = (byte)i;
return new UInt4((a._value + b._value) & MaxValue);
}
Is istnieje sposób zadeklarowania dwóch przeciążeń operatora dodawania, jeden sprawdzony, a drugi niezaznaczony? Ewentualnie, czy jest jakiś sposób, aby określić w czasie wykonywania kontekst wywołującego (co wydaje się mało prawdopodobne, ale pomyślałem, że mimo to zapytać), coś takiego:
public static UInt4 operator +(UInt4 a, UInt4 b)
{
byte result = (byte)(a._value + b._value);
if (result > MaxValue)
if (ContextIsChecked())
throw new OverflowException();
else
result &= MaxValue;
return new UInt4(result);
}
private static bool ContextIsChecked()
{
throw new NotImplementedException("Please help.");
}
Oto odpowiedź http://stackoverflow.com/questions/2873765/how-to-find-out-the-current-overflow-checking-context, która mówi, że jest mniej lub bardziej niemożliwa ... Czekam, aby zobaczyć Twoje podejście ... –
@AlexeiLevenkov odpowiedź, którą znalazłem również wskazuje, że jest to niemożliwe. Jednym z podejść, o którym pomyślałem, jest zdefiniowanie typów "UInt4Checked" i "UInt4Unchecked" z wyraźnymi konwersjami między nimi. – phoog
Downvoter, proszę wyjaśnić. – phoog