Я тестировал и получил следующее:
class A {
public $property;
}
function set_property($obj) {
$obj->property = "after";
var_dump($obj);
}
$a = new A();
$a->property = "before";
// Creates a new Object from $a. Like "new A();"
$b = new $a;
// Makes a Copy of var $a, not referenced.
$c = clone $a;
set_property($a);
// object(A)#1 (1) { ["property"]=> string(5) "after" }
var_dump($a); // Because function set_property get by reference
// object(A)#1 (1) { ["property"]=> string(5) "after" }
var_dump($b);
// object(A)#2 (1) { ["property"]=> NULL }
var_dump($c);
// object(A)#3 (1) { ["property"]=> string(6) "before" }
// Now creates a new obj A and passes to the function by clone (will copied)
$d = new A();
$d->property = "before";
set_property(clone $d); // A new variable was created from $d, and not made a reference
// object(A)#5 (1) { ["property"]=> string(5) "after" }
var_dump($d);
// object(A)#4 (1) { ["property"]=> string(6) "before" }
?>
Нет никакого неявного преобразования от Nullable<bool>
до bool
. Там неявное преобразование от bool
до Nullable<bool>
, и это - то, что происходит (в терминах языка) к каждой из bool констант в первой версии. bool operator==(Nullable<bool>, Nullable<bool>
оператор затем применяется. (Это не вполне то же как другие снятые операторы - результат всего bool
, не Nullable<bool>
.)
, Другими словами, выражение 'fred == ложь' имеет тип bool
, тогда как выражение 'fred' имеет тип Nullable<bool>
следовательно, Вы не можете использовать его в качестве "если" выражение.
РЕДАКТИРОВАНИЕ: Для ответа на комментарии никогда нет неявного преобразования от Nullable<T>
до [1 110] и на серьезном основании - неявные преобразования не должны выдавать исключения, и если Вы не хотите null
быть неявно преобразованными в [1 112] много еще нет, который мог быть сделан.
кроме того, если бы там были неявные преобразования оба окольных пути, выражение как "nullable + не допускающий NULL-значения" очень сбивало бы с толку (для типов, которые поддерживают +, как [1 113]). Оба + (T?, T?) и + (T, T) было бы доступно, в зависимости от которого операнда были преобразованы - но результаты могли очень отличаться!
я - 100% позади решения только иметь явное преобразование от [1 114] до [1 115].
Поскольку fred не является булевской переменной. это - структура, которая имеет булево свойство под названием IsNull или HasValue, или безотносительно... Объект, названный fred, является сложным составным объектом, содержащим булевскую переменную и значение, не саму примитивную булевскую переменную...
Ниже, например, то, как мог быть реализован Интервал Nullable. Универсальный Nullable почти наверняка реализован так же (но в общем). Вы видите здесь, как неявные и явные преобразования реализованы..
public struct DBInt
{
// The Null member represents an unknown DBInt value.
public static readonly DBInt Null = new DBInt();
// When the defined field is true, this DBInt represents a known value
// which is stored in the value field. When the defined field is false,
// this DBInt represents an unknown value, and the value field is 0.
int value;
bool defined;
// Private instance constructor. Creates a DBInt with a known value.
DBInt(int value)
{
this.value = value;
this.defined = true;
}
// The IsNull property is true if this DBInt represents an unknown value.
public bool IsNull { get { return !defined; } }
// The Value property is the known value of this DBInt, or 0 if this
// DBInt represents an unknown value.
public int Value { get { return value; } }
// Implicit conversion from int to DBInt.
public static implicit operator DBInt(int x)
{ return new DBInt(x); }
// Explicit conversion from DBInt to int. Throws an exception if the
// given DBInt represents an unknown value.
public static explicit operator int(DBInt x)
{
if (!x.defined) throw new InvalidOperationException();
return x.value;
}
public static DBInt operator +(DBInt x)
{ return x; }
public static DBInt operator -(DBInt x)
{ return x.defined? -x.value: Null; }
public static DBInt operator +(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value + y.value: Null;
}
public static DBInt operator -(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value - y.value: Null;
}
public static DBInt operator *(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value * y.value: Null;
}
public static DBInt operator /(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value / y.value: Null;
}
public static DBInt operator %(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value % y.value: Null;
}
public static DBBool operator ==(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value == y.value: DBBool.Null;
}
public static DBBool operator !=(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value != y.value: DBBool.Null;
}
public static DBBool operator >(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value > y.value: DBBool.Null;
}
public static DBBool operator <(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value < y.value: DBBool.Null;
}
public static DBBool operator >=(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value >= y.value: DBBool.Null;
}
public static DBBool operator <=(DBInt x, DBInt y)
{
return x.defined && y.defined?
x.value <= y.value: DBBool.Null;
}
public override bool Equals(object o)
{
try { return (bool) (this == (DBInt) o); }
catch { return false; }
}
public override int GetHashCode()
{ return (defined)? value: 0; }
public override string ToString()
{ return (defined)? .ToString(): "DBInt.Null"; }
}
Оператор Nullable<bool> == true
неявно проверяет Nullable<bool> == (Nullable<bool>)true
.
Примечание, что Nullable<bool>
само не булевская переменная. Это - обертка для булевской переменной, которая может также быть установлена в NULL.
При кастинге fred к булевской переменной он скомпилирует:
if (( bool )fred )
(...)
я думаю это, когда Вы сравниваете bool? к bool компилятор делает бросок implicite, сделайте сравнение и затем возвратите TRUE или FALSE. Результат: выражение оценивает к bool.
, Когда Вы не сравниваете bool? к чему-то выражение оценивает к bool?, кто недопустим там.
Технически простой условный тест не требует неявного преобразования в bool, если у вас есть реализация оператора true.
bool? nullableBool = null;
SqlBoolean sqlBoolean = SqlBoolean.Null;
bool plainBool = sqlBoolean; // won't compile, no implicit conversion
if (sqlBoolean) { } // will compile, SqlBoolean implements true operator
Исходный вопрос заключается в поиске реализации NULL в стиле SQL, где NULL рассматривается как неизвестное, а реализация Nullable больше похожа на добавление NULL в качестве дополнительного возможного значения. Например, сравните:
if (((int?)null) != 0) { } //block will execute since null is "different" from 0
if (SqlInt32.Null != 0) { } // block won't execute since "unknown" might have value 0
Более похожее на базу данных поведение доступно из типов в System.Data.SqlTypes