In C# 7.2, we saw the introduction of the in modifier for method parameters to pass read-only references to objects. I'm working on a new .NET Standard project using 7.2, and out of curiosity I tried compiling with the in keyword on the parameters for the equality operators for a struct.
i.e. - public static bool operator == (in Point l, in Point r)
not - public static bool operator == (Point l, Point r)
I was initially a bit surprised that this worked, but after thinking about it a bit I realized that there is probably no functional difference between the two versions of the operator. I wanted to confirm these suspicions, but after a somewhat thorough search around, I can't find anything that explicitly talks about using the in keyword in operator overloads.
So my question is whether or not this actually has a functional difference, and if it does, is there any particular reason to encourage or discourage the use of in with operator arguments. My initial thoughts are that there is no difference, particularly if the operator is inlined. However, if it does make a difference, it seems like in parameters should be used everywhere (everywhere that readonly references make sense, that is), as they provide a speed bonus, and, unlike ref and out, don't require the user to prepend the those keywords when passing objects. This would allow more efficient value-type object passing without a single change on the user of the methods and operators.
Overall, this may go beyond the sort of small-scale optimizations that most C# developers worry about, but I am curious as to whether or not it has an effect.
whether or not this actually has a functional difference... My initial thoughts are that there is no difference, particularly if the operator is inlined
Since the operator == overload is invoked like a regular static method in MSIL, it has the functional difference. It can help to avoid unnecessary copying like in a regular method.
is there any particular reason to encourage or discourage the use of in with operator arguments.
According to this article it is recommended to apply in modifier when value types are larger than System.IntPtr.Size. But it is important that the value type should be readonly struct. Otherwise in modifier can harm the performance because the compiler will create a defensive copy when calling struct's methods and properties since they can change the state of the argument.
Related
I recently started on WPF, and I noticed that you have to do a lot of casting (especially with events). This is an aesthetic issue, but I was wondering how bad it would be if I'd use an extension method to cast, instead of using normal casting.
public static T Cast<T>(this object obj)
{
return (T)obj;
}
This would mean I could prevent a few nested parantheses, and change:
Console.WriteLine(((DataGridCell)e.OriginalSource).ActualHeight);
to:
Console.WriteLine(e.OriginalSource.Cast<DataGridCell>().ActualHeight);
Are there any clear disadvantages that I might be overlooking? How disgusted will people be when they encounter this in code? :)
This is similar in intent to Enumerable.Cast, so I wouldn't necessarily say that people will be disgusted.
Are there any clear disadvantages that I might be overlooking?
The main disadvantage is that this will be an extension method available to every single variable in your code, since you're extending System.Object. I typically avoid extension methods on Object for this reason, as it "pollutes" intellisense.
That being said, there are other disadvantages:
If you used this on an existing IEnumerable, you'd get a name collision with Enumerable.Cast<T>. A file having your namespace included but missing a using System.Linq could easily be misunderstood by other developers, as this would have a very different meaning to the expected "Cast<T>" extension method.
If you use this on a value type, you're introducing boxing (pushing the value type into an object), then an unbox and cast, which can actually cause an exception that wouldn't occur with a cast. Your extension method will raise an exception if you do:
int i = 42;
float f = i.Cast<float>();
This might be unexpected, as float f = (float)i; is perfectly legal. For details, see Eric Lippert's post on Representation and Identity. If you do write this, I would definitely recommend adding a class constraint to your operator.
I, personally, would just use parenthesis. This is a common, language supported feature, and should be understandable to all C# developers. Casting has the advantages of being shorter, understandable, and side effect free (in terms of intellisense, etc).
The other option would be to make this a normal static method, which would allow you to write:
Console.WriteLine(Utilities.Cast<DataGridCell>(e.OriginalSource).ActualHeight);
This eliminates the disadvantage of "polluting" intellisense, and makes it obvious that its a method you wrote, but increases the amount of typing required to use. It also does nothing to prevent the boxing and unbox/cast issue.
The main disadvantage is that casting is well-known for every C# developer, while your Cast<T> method is just another not-invented here wheel. The next step, usually, is a set of extensions like IsTrue, IsFalse, IsNull, etc.
This is a syntax garbage.
Currently I'm teaching a class of C++ programmers the basics of the C# language. As we discussed the topic operators I used C# standard categories of primary, unary etc. operators.
One of the attendees felt puzzled, because in the C# standard the "postfix ++/--" have been put in the category of primary operators rather than the "prefix ++/--". Her rationale behind this confusion was, that she would rather implement the C++ operator "postfix ++/--" in terms of the operator "prefix ++/--". In other words she would rather count the operator "prefix ++/--" as a primary operator. - I understand her point, but I can't give to her a rationale behind that. OK the operators "postfix ++/--" have a higher precedence than "prefix ++/--", but is this the only rationale behind that?
The spec mentioned it in section "14.2.1 Operator precedence and associativity".
So my very neutral question: Why are Postfix ++/-- categorized as primary Operators in C#?
Is there a deeper truth in it?
Since the ECMA standard itself does not define what a 'Primary' operator is, other than order of precedence (i.e. coming before 'Unary') there can be no other significance. The choice of words was probably bad.
Take into account that in many C-link languages, postfix operators tend to create a temporary variable where the expression's intermediate result is stored (see: "Prefer prefix operators over postfix" at Semicolon). Thus, they are fundamentally different from the prefix version.
Nonetheless, quickly checking how Mono and Visual Studio compile for-loops using the postfix and prefix forms, I saw that the IL code produced is identical. Only if you use the postfix/prefix expression's value does it translate to different IL (only affecting where the 'dup' instruction in placed), at least with those implementations mentioned.
EDIT: Okay, now I'm back home, I've removed most of the confusing parts...
I don't know why x++ is classified as a primary expression but ++x isn't; although I doubt it makes much difference in terms of the code you would write. Ditto precedence. I wonder whether the postfix is deemed primary as it's used more commonly? The annotated C# specs don't have any annotations around this, by the way, in either the ECMA edition or the Microsoft C# 4 editions. (I can't immediately find my C# 3 edition to check.)
However, in terms of implementation, I would think of ++ as a sort of pseudo-operator which is used by both prefix and postfix expressions. In particular, when you overload the ++ operator, that overload is used for both postfix and prefix increment. This is unlike C++, as stakx pointed out in a comment.
One thing to note is that while a post-increment/post-decrement expression has to have a primary expression as an operand, a pre-increment/pre-decrement expression only has to have a unary expression as an operand. In both cases the operand has to be classified as a variable, property access or indexer access though, so I'm not sure what practical difference that makes, if any.
EDIT: Just to give another bit of commentary, even though it seems arbitrary, I agree it does seem odd when the spec states:
Primary expressions include the simplest forms of expressions
But the list of steps for pre-increment is shorter/simpler than list of steps for post-increment (as it doesn't include the "save the value" step).
the difference is that
a[i++] will access the element indexed i.
a[++i] will access teh element indexed i+1.
In both cases after execution of a[++i/i++]
i will be i+1.
This can make troubles because you can't make assumption on parameters order
function(i++,i++,i++)
will increment i 3 times but you don't know in wich order. if initially i is 4 you can also have
function(4,5,6)
but also function(6,5,4)
or also function(6,4,5).
and that is still nothing because I used as example native types (for example "int"), things get worse when you have classes.
When overloading the operator result is not changed, what is changed is it's precedence. and this too can cause troubles.
So in one case "++" is applied before returning the reference, in the other case is applied "after" returning the reference. And when you overload it probably is better having it applied before returnin the reference (so ++something is much better than something++ at least from overloading point of view.)
take a generic class with overloaded ++ (of wich we have 2 items, foo and bar)
foo = bar ++; //is like writing (foo=bar).operator++();
foo = ++bar; // is like writing foo= (bar.operator++());
and there's much difference. Especially when you just don't assign your reference but do something more complex with it, or internally your object has stuff that has to do with shallow-copies VS deep copies.
I am learning C# and .NET, and I frequently use the keyword var in my code. I got the idea from Eric Lippert and I like how it increases my code's maintainability.
I am wondering, though... much has been written in blogs about slow heap-located refs, yet I am not observing this myself. Is this actually slow? I am referring to slow compile times due to type inferencing.
You state:
I am referring to slow time for compile due to type 'inferencing'
This does not slow down the compiler. The compiler already has to know the result type of the expression, in order to check compatibility (direct or indirect) of the assignment. In some ways using this already-known type removes a few things (the potential to have to check for inheritance, interfaces and conversion operators, for example).
It also doesn't slow down the runtime; they are fully static compiled like regular c# variables (which they are).
In short... it doesn't.
'var' in C# is not a VARIANT like you're used to in VB. var is simply syntactic sugar the compiler lets you use to shorthand the type. The compiler figures out the type of the right-hand side of the expression and sets your variable to that type. It has no performance impact at all - just the same as if you'd typed the full type expression:
var x = new X();
exactly the same as
X x = new X();
This seems like a trivial example, and it is. This really shines when the expression is much more complex or even 'unexpressable' (like anonymous types) and enumerables.
Var is replaced at compile time with your actual variable type. Are you thinking of dynamic?
A "variant" is typeless, so access to state (or internal state conversion) always must go through two steps: (1) Determine the "real" internal type, and (2) Extract the relevant state from that "real" internal type.
You do not have that two-step process when you start with a typed object.
True, a "variant" thus has this additional overhead. The appropriate use is in those cases where you want the convenience of any-type for code simplicity, like is done with most scripting languages, or very high-level APIs. In those cases, the "variant" overhead is often not significant (since you are working at a high-level API anyway).
If you're talking about "var", though, then that is merely a convenience way for you to say, "Compiler, put the proper type here" because you don't want to do that work, and the compiler should be able to figure it out. In that case, "var" doesn't represent a (runtime) "variant", but rather a mere source-code specification syntax.
The compiler infers from the constructor the type.
var myString = "123"; is no different from string myString = "123";
Also, generally speaking, reference types live on the heap and value types live on the stack, regardless if they're declared using var.
I'm a C# programmer writing Java (for Android) and have a few technicalities of Java I'm still not sure about, and worried I'm approaching from a C# angle:
Are parameters in methods passed in the same manner as C#? (Copied for reference types)
Why has the #Override attribute suddenly appeared (I think it's Java 1.5+?)
How is possible to compile an application, if you are missing a dependency for one of the libraries you're using?
Do I need to worry about using += for large string concatenation (e.g. use a StringBuilder instead)
Does Java have operator overloading: should I use equals() or == by default. Basically is object.equals roughly the same as C# (reflection for value types, address reference for reference types)
Answering in order:
Yes, arguments are passed by value in Java, always. That includes references, which are copied (rather than objects being copied). Note that Java doesn't have any equivalent of ref or out
#Override allows you to catch typos at compile-time, just like the "override" modifier in C#
You compile an application only against the libraries you're using. There's no transitive dependency checking, just like there isn't in .NET.
Yes, you should avoid concatenating strings in a loop, just like in .NET. Single-statement concatenation is fine though, just as it is in .NET - and again, the compiler will perform concatenation of constant expressions at compile time, and string literals are interned.
No, Java doesn't have user-defined operator overloading. There are no custom value types in Java; == always compares the primitive value or the reference. (If you compare an Object reference and a primitive value, autoboxing/unboxing gets involved, and I can never remember which way round this works. It's a bad idea though, IMO.)
Are parameters in methods passed in
the same manner as C#? (Copied for
reference types)
All primative types are copied, all objects are actually pointers to objects, the pointer is copied, but the actual object isn't copied.
Why has the #Override attribute
suddenly appeared (I think it's Java
1.5+?)
It hasn't, since Java 1.6 you can also use it to show a method is implementing an interface. The #Override allows you to indicate to the compiler that you think you are overriding a method, the compiler will warn you when you aren't (this is very useful actually, especially if the super class changes)
How is possible to compile an
application, if you are missing a
dependency for one of the libraries
you're using?
I don't think it is.
Do I need to worry about using += for
large string concatenation (e.g. use a
StringBuilder instead)
In some cases. The java compiler + VM is very good at automatically using StringBuilder for you. However it will not always do this. I wouldn't optimize for this (or anything) beforehand.
Does Java have operator overloading:
should I use equals() or == by
default. Basically is object.equals
roughly the same as C# (reflection for
value types, address reference for
reference types)
No it doesn't have operator overloading.
About String concatenation I think it depends if you add static strings together or if you concatene variables. With variables it's better to use StringBuilder. :).
So :
String s = "A";
s += "B";
s += "C";
is fine.
But here it's better with StringBuilder
String s = "A";
s += variable_b;
s += variable_c;
I enjoy and highly recommend Juval Lowy's - C# Coding Standard. Juval explicitly avoids rationale for each directive in order to keep the standard tight (see the preface). However, there are a few directives for which I find myself curious as to the rationale.
What is the specific rationale to the following directives from Lowy's C# standard?
Hopefully there are hard (non-subjective) answers to these.
1.13 Avoid fully qualified type names. Use the "using" statement instead.
Is this a performance issue? Sometimes I only need one instance of the fully qualified name and adding a using seems heavy.
1.26 Use empty parenthesis on parameterless-anonymous methods. Omit the parenthesis only if the anonymous method could have been used on any delegate.
Actually I am just confused by the second sentence. Explanation with example(s) would help, thank you.
2.19 Avoid defining custom exception classes
What are the considerations in minimizing their numbers? (He next gives guidelines if you do define them (in 2.20).)
2.29 Avoid using the ternary conditional operator
Too hard for the reader to digest, or other considerations?
2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.
I don't think I do this, but I am curious...why not?
2.47 Avoid interfaces with one member.
Because it is always/usually more prefereable to do what? One method interfaces work when?
2.53 Prefer using explicit interface implementation
Why? Also, Jon Skeet disagrees here.
Thanks in advance!
Robert
2.29 Avoid using the ternary conditional operator I have no problems with "simple" uses of the ternary operator but have recommended against using it in a nested fashion:
// This is fine
x := (conditionA) ? true_resultA : false_resultA;
// This would probably be clearer using if-then-elseif
x := (conditionA) ?
((conditionA1) ? true_resultA1 : (condition2) ? true_result2 : false_result2) :
((conditionA2) ? true_resultA2 : false_resultA2);
Obviously, I'm not Juval, but I can take a stab at these
1.13 Avoid fully qualified type names. Use the "using" statement instead.
Performance can't be the issue here. I'm sure the issue is readability.
1.26 Use empty parenthesis on parameterless-anonymous methods. Omit the parenthesis only if the anonymous method could have been used on any delegate.
public delegate void Foo1();
public delegate void Foo2(int val);
public void Foo()
{
Foo1 first = delegate { Console.WriteLine("Hello world"); };
Foo2 second = delegate { Console.WriteLine("Hello world"); };
Foo1 third = delegate() { Console.WriteLine("Hello world"); };
Foo2 fourth = delegate() { Console.WriteLine("Hello world"); }; // does not compile
}
Without the parens, the anonymous delegate can be applied to any delegate. With the parens, you're being specific about the signature of the delegate. Prefer the second syntax unless you really need the flexibility.
2.19 Avoid defining custom exception classes
Again, readability is the issue here. The framework exception classes are rich and well-understood. Be wary when replacing them.
2.29 Avoid using the ternary conditional operator
It's a readability and expandability thing. I don't really agree, but it's a standard religious fight.
2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.
Partially this is readability, and partially it's for ease of debugging. I've starting to assign almost everything to temporary variables just so that they're easily found in the debugger later on.
2.47 Avoid interfaces with one member.
"Avoid" is kinda like "prefer", he's just saying think twice before you do it. If you only have one member, is the interface really modeling something useful and complete in your design? It's pretty rare to have a class with just one member, think seriously about why your interface is any different.
2.53 Prefer using explicit interface implementation
This is similar to the idea of using the least-public accessor you can. If your class doesn't need to make the interface public, then it probably shouldn't. This is going to differ significantly based on your design, obviously, but given the fact that most people just make the interface implicit without really thinking about it, it's advice worth considering.
1.26 is about pre-lambda delegate { } syntax.
// #1 Empty parenthesis on parameterless-anonymous methods would be:
delegate() { }
// #2 ... anonymous method could have been used on any delegate, is:
delegate { }
Remember, the latter can be assigned to any delegate, regardless of its parameters. The delegate just ignores these using some compiler trickery.
If you define a delegate taking no parameters, explicitly say so using #1. Don't "leave the parenthesis out because your delegate doesn't take any parameters anyway".
Regarding 1.13 (Avoid fully qualified type names. Use the "using" statement instead):
It may be a bit more than readability. If you have too many usings at the beginning of the file, you have a class that is coupled with classes from too many namespaces.
The class is screaming out for refactoring. Using usings instead of fully-qualified class names lets you identify such tightly-coupled classes more easily.
A lot of these guidelines speak to the "quality attributes" of good software design (i.e. maintainability, reliability, reusability, testability, expandability, debugability, interoperability, and what other -ilities you can name).
Often people create code that works fine at the time but may not be the best choice when considering all the quality attributes (in the sense of "where can this software go in the future" or "someone else has to use this code, too").
For example:
2.29 Avoid using the ternary conditional operator
I have no problem with ternary expressions, per se, but by writing code such as: int result = CheckMethod() ? OnTrueDoThis() : OnFalseDoThat()... you are saying, "I have a conditional that, if true (or false), you can do one and only one thing." The whole construct discourages expandability. You have to recreate the construct (with an if..else statement).
Similarly...
2.31 Avoid function calls in Boolean conditional statements. Assign into
local variables and check on them.
You called a function and essentially "discarded" the results for later use. If that information is needed later, either the function would have to be called again or the structure of the code would have to be rewritten. It would also make checking or logging the results (for future debugging) more difficult.
This is my best stab at the questions you've listed. For the ones that I can't really say, I've omitted.
1.13 Avoid fully qualified type names. Use the "using" statement instead.
Readability. It's must harder to read code when you have to read fully qualified type names.
2.19 Avoid defining custom exception classes
The .NET framework comes with a good set of exceptions built into the system. Unless the exception you're modeling is business domain specific, you'll probably be able to use one of the existing exception classes.
2.29 Avoid using the ternary conditional operator
I think this is most likely because he thinks people may not understand the operator, but I disagree.
2.47 Avoid interfaces with one member.
He might be warning people of building interfaces that are too thin. However, I would actual say the converse, warning people of making interfaces too verbose. If you've ever had to deal with ASP.NET MembershipProvider, you know what I'm talking about.
2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.
A couple of reasons I can think of here. Readability. It can make conditional statements hard to understand if you are making function calls in them. Also, it's harder to debug if you're not watching.
2.53 Prefer using explicit interface implementation
I believe his reasoning here is to for brevity. However, I don't actually agree with this assessment. I think Jon is correct, implicit interface should be used when you can, and explicit when appropriate.
Here are some of my reactions of which I dare answer them :)
1.13 Avoid fully qualified type names. Use the "using" statement instead.
I disagree. It's certainly not performance related. It can lead to improved readability to have var foo = new Foo() instead var foo = new MyCompany.MyNamespace.Helpers.Xml.Foo() but other than that - no.
2.19 Avoid defining custom exception classes
This is nonsense imho. You should avoid creating custom exceptions that derive from ApplicationException, but there is nothing wrong with custom exceptions (as long as you're not going to reinvent existing exceptions that is).
2.29 Avoid using the ternary conditional operator
I have no idea why that would be a guideline. I have read that not all people use it and may not recognize it, but that is not a valid reason to not use a useful operator.
2.31 Avoid function calls in Boolean conditional statements. Assign into local variables and check on them.
This is simply a readability issue in my opinion.
2.47 Avoid interfaces with one member.
I also disagree here. You should avoid 'marker' interfaces though - interfaces with no marker, but who just serve the purpose that something is '...ble'. But, one method on an interface seems fine to me.
2.29 Ternary operator
To start with, if you start to use the ternary operator, there should be a reason for the use of the ternary operator over a regular if-then-else. Observe :
if (x == 0) {...} else{...} //A set of statements demand a regular If-then-else
//A simple assignment can be handled by the ternary operator
y = (x == 0)? 1 : 0 //this is readable and how it should be used
(x==0)? callSomething() : callSomethingElse() //this is NOT how it should be used
The ternary statement is meant for returning one of two values depending upon the conditional it is evaluating. This is extremely handy when doing FP. For call statements that do not return a value, you should revert to if-then-else.