Is there default assignment operator in c#?
Unlike C++, C# does not allow you to override the assignment operator.
For reference types, writing x = y will set x to refer to the same object (or null) that y does.
For value types, writing x = y will copy the fields in the y value to the x value.
Related
I have the following construct:
MyType y = x.HasValue ? f(x) : null;
I am aware of a simple pattern that can be used if f was a member of x: MyType y = x.?f();
Is there a similar way to simplify the above code without changing the definition of f?
At present (November 2015), no such mechanism exists in C#.
Options are:
Change f to return null when parameters are null
Make an extension method
static R Call<P>(this P? parameter, Func<P, R> func)
{
if (parameter.HasValue)
return func(parameter.Value);
else
return default(R);
}
The closest thing I can think of is the null coalescing operator '??'
From MSDN:
// Set y to the value of x if x is NOT null; otherwise
// if x == null, set y to -1
y = x ?? -1;
Assuming f() can handle x being null and will return null if not, but then you could just do MyType y = f(x), which sounds like your best bet. Keep in mind, anything other than changing the function to handle x being null would require you to remember to do it on your own, as well as remember why, thus creating room to shoot your own foot and removing a layer of abstraction.
Also, doesn't f(x) take a nullable type and is therefore expecting one anyways?
Why does the following crash with a NullReferenceException on the statement a.b.c = LazyInitBAndReturnValue(a);?
class A {
public B b;
}
class B {
public int c;
public int other, various, fields;
}
class Program {
private static int LazyInitBAndReturnValue(A a)
{
if (a.b == null)
a.b = new B();
return 42;
}
static void Main(string[] args)
{
A a = new A();
a.b.c = LazyInitBAndReturnValue(a);
a.b.other = LazyInitBAndReturnValue(a);
a.b.various = LazyInitBAndReturnValue(a);
a.b.fields = LazyInitBAndReturnValue(a);
}
}
Assignment expressions are evaluated from right to left, so by the time we are assigning to a.b.c, a.b should not be null. Oddly enough, when the debugger breaks on the exception, it too shows a.b as initialized to a non-null value.
This is detailed in Section 7.13.1 of the C# spec.
The run-time processing of a simple assignment of the form x = y
consists of the following steps:
If x is classified as a variable:
x is evaluated to produce the variable.
y is evaluated and, if required, converted to the type of x through an implicit conversion (Section 6.1).
If the variable given by x is an array element of a reference-type, a run-time check is performed to ensure that the value
computed for y is compatible with the array instance of which x is an
element. The check succeeds if y is null, or if an implicit reference
conversion (Section 6.1.4) exists from the actual type of the instance
referenced by y to the actual element type of the array instance
containing x. Otherwise, a System.ArrayTypeMismatchException is
thrown.
The value resulting from the evaluation and conversion of y is stored into the location given by the evaluation of x.
If x is classified as a property or indexer access:
The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent set accessor invocation.
y is evaluated and, if required, converted to the type of x through an implicit conversion (Section 6.1).
The set accessor of x is invoked with the value computed for y as its value argument.
I think the bottom section (if x is classified as a property or indexer access) provides a hint, but perhaps a C# expert can clarify.
A set accessor is generated first, then y is evaluated (triggering your breakpoint), then the set accessor is invoked, which causes a null reference exception. If I had to guess, I'd say the accessor points to the old value of b, which was null. When you update b, it doesn't update the accessor that it already created.
I realize this doesn't answer your question, but allowing something outside of class A to initialize a member belonging to class A in this fashion seems to me to break encapsulation. If B needs to be initialized on first use the "owner" of B should be the one to do that.
class A
{
private B _b;
public B b
{
get
{
_b = _b ?? new B();
return _b;
}
}
}
Does C# have an equivalent to JavaScript's assignment syntax var x = y || z;? In case you don't know, the result is not true/false. If y is defined, then it is assigned to x, otherwise z is assigned to x even if it is undefined.
Note that in JavaScript the variable still has to be declared: var test;
I think that you are looking for ?? operator.
MSDN Reference
var abc = blah ?? "default";
yep
This is what you are looking for
var x = y ?? z;
In C# there's no such notion as variable not being defined. Such operator doesn't make sense in C#.
Unlike JavaScript, C# is not dynamic but static language so that such operation is impossible - a compilation error will occur.
Imagine you're writing this if:
if(pizzaPrice == hamburgerPrice)
Before declaring the variables first:
decimal pizzaPrice;
decimal hamburgerPrice;
An error will occur on compile-time.
Update:
Even if the variables were declared it doesn't matter because C# does not support such a feature.
On the other hand, JavaScript is enforcing evaluation of the variable in if conditions by calling the ToBoolean method and if it's undefined or null it's equals to false and C# doesn't not contains such a behavior.
Look at this cool article: JavaScript pitfalls: null, false, undefined, NaN
But if you want to check if a variable is referencing to a null you can easily use the null coalescing operator "??" operator.
As the following:
var x = y ?? z;
Yes, there is: ??
string x = y ?? z;
Which basically calculates:
string x = y != null ? y : z
However, there are a few differences between Javascript and C#. As with JS, y and z must both be declared before hand. However, unlike JS, y and z must also be "assigned" in C# or a compiler error will be thrown as usual.
The operator requires a nullable type and it checks whether the first is null before returning the second. You can chain a whole bunch (a ?? b ?? c ?? d ?? e) if you want.
Note that a zero length string is not null.
Can someone please explain me the logic reason why I must cast null to int?
When the left argument type can have their both types ?
Insted of doing
int? k = (DateTime.Now.Ticks%5 > 3 ? 1 : null);
I must do
int? k = (DateTime.Now.Ticks%5 > 3 ? 1 : (int?) null);
although int? k = null is perfectly valid.
An opposite example :
I didn't have to do it in:
string k = (DateTime.Now.Ticks%5 > 3 ? "lala" : null);
int? k = (DateTime.Now.Ticks%5 > 3 ? 1 : (int?) null);
In this case what we have is 1 is int and null is actually null
Now the confusion is the ternary operator is confused as what is the return type int or well null and since its int it won't accept null
So you would need to cast it to a nullable int
Now in the other case you have a string and null is perfectly acceptable for a string
Further explanation can be found at Type inference - Eric
The second and third operands of the ?: operator control the type of
the conditional expression. Let X and Y be the types of the second and
third operands. Then,
If X and Y are the same type, then this is the type of the conditional expression.
Otherwise, if an implicit conversion exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
Otherwise, if an implicit conversion exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
Otherwise, no expression type can be determined, and a compile-time error occurs.
Because the compiler doesn't use the type of the variable in the left hand side to determine the type of the expression on the right hand side. First it determines what type the expression is, then it determines if it's possible to put it in the variable.
There is no type close enough that is common between an int and a null value. You have to either make the int value nullable or the null value "intable" for the compiler to find a common ground for the values.
When you have a string and a null value the compiler can simply use one of the types, because a string is already nullable.
Reading C# In Depth, 2nd edition, section 2.1.2 on combining and removing delegates.
The subsection title states that "delegates are immutable" and that "nothing about them can be changed." In the next paragraph, though, it talks about using constructs like
x += y;
where x and y are variables of compatible delegate types.
Didn't I just change x? Or does the immutability part deal with when x is disposed of when I do this (i.e., immediately)?
That's like doing:
string x = "x";
string y = "y";
x += y;
Strings are immutable too. The code above not changing the string objects - it's setting x to a different value.
You need to differentiate between variables and objects. If a type is immutable, that means that you can't change the data within an instance of that type after it's been constructed. You can give a variable of that type a different value though.
If you understand how that works with strings, exactly the same thing is true with delegates. The += actually called Delegate.Combine, so this:
x += y;
is equivalent to:
x = Delegate.Combine(x, y);
It doesn't change anything about the delegate object that x previously referred to - it just creates a new delegate object and assigns x a value which refers to that new delegate.
You have changed x, but didn't change its value (i.e. the delegate it was holding).
It's the same as:
int num = 4;
num += 2;