Search Unity

A C# code beginner: Where can I make the suggestion for a C# improvement ?

Discussion in 'Scripting' started by AlanMattano, Aug 5, 2016.

  1. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,501
    I was trying to make more compact my code with no success.

    Code (CSharp):
    1. public bool printInConsole;
    2.  
    3. void Start()
    4. {
    5.     if ( printInConsole )
    6.         Debug.Log("Starting and printing...");
    7. }
    Stack Overflow Question link

    Is not posible to make something like this:

    Code (CSharp):
    1. public bool printInConsole;
    2.  
    3. void Start()
    4. {
    5.     printInConsole ?
    6.         Debug.Log("Starting and printing...");
    7. }
    For some of you this looks stupid. I'm a beginner and for me, It looks nice and clean. There is much less to type in. I'm new at coding.

    Where can I make the suggestion for C# improvement ?
    Sorry if I ask here and is not the best place.
     
    Last edited: Aug 6, 2016
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    less characters doesn't mean "better" code; verbose, well formatted (whitespace, indents etc.), commented code with consistently named descriptive functions and variables so you (or someone else) can pick the same code in 6 months time and understand it straight away is much "better" :D
     
  3. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    As far as the .net implementation of c# you can go here: https://aspnet.uservoice.com/forums/41199-general-asp-net
    And for Mono you can go here: http://www.mono-project.com/community/

    Unity uses an older version of Mono though, so even if either of the two implementations support the idea you have, I doubt it will be in Unity any time soon.

    That said I agree with @LeftyRighty and in case of your example, I don't really like it. I don't even like the first sample though, as I believe the statement and code execution belong on separate lines, preferably (especially in longer methods) with curly braces as well.
     
    AlanMattano likes this.
  4. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    Code properly.

    if (condition)
    {
    statement;
    }
     
    xjjon likes this.
  5. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    612
    You are only typing 3 less characters..
     
  6. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    What you're suggesting already exists. It's known as a ternary conditional. Several languages including C# support it.

    https://en.wikipedia.org/wiki/?:
    https://msdn.microsoft.com/en-us/library/zakwfxx4(v=vs.100).aspx

    Code (CSharp):
    1. public bool printInConsole;
    2.  
    3. void Start()
    4. {
    5.     Debug.Log(printInConsole ? "Starting and printing..." : "");
    6. }
    What others have said though, both in this thread and in an article on Stack Overflow that I'll link, is spot on. It doesn't improve readability. At least not in the vast majority of situations and even for the handful of situations that do you aren't going to spend any meaningful length of time on those portions of code.

    http://stackoverflow.com/questions/3312786/benefits-of-using-the-conditional-ternary-operator
     
    RavenOfCode and AlanMattano like this.
  7. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,501
    Just in case, here is the suggestion link
    Thanks all for the nice and clear answers.

    Code (CSharp):
    1. Debug.Log(printInConsole ? "Running and printing..." : "\n");
    Brilliant @Ryiah you are a Master! I did not know I could implement it inside a function.

    Ps: and congratulations for your 7000 contribuciones!
     
    Last edited: Aug 6, 2016
  8. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    The ternary conditional returns a value as if it were a function.
    Code (csharp):
    1. value = expression ? true_value : false_value;
    Anything that accepts a value or a variable can accept the results of the ternary.

    The previous example could be done this way too.
    Code (csharp):
    1. string s = printInConsole ? "Starting and printing..." : "";
    2. Debug.Log(s);
     
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    C# is 16 years old, and s used by millions of developers in the entire range of software development. The syntax is further inspired by C, which is a standard that's 44 years old. There's a large committee with industry veterans that work with the community on developing the language. It's developed by Microsoft.

    What I'm trying to say here is that your input might not get through.
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    It's worth noting that an empty Debug.Log statement still does the stack trace. You are better off going with the original which skips the statement altogether, rather then using an empty string.
     
    Ryiah likes this.
  11. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,501
    Yes, I can imagine my petition is launching a paper airplane. I'm learning and discovering that is also part of the process. Thanks

    I think that a new conditional compact if statement using only the operator (?) by taking out the ( : ) the ternary and transform it into a simple more compact if without else, can be useful only when the resulting statement is extremely short and represents a significant increase in conciseness over the if equivalent without sacrificing readability as explain in the Ryiah link benefits-of-using-the-conditional-ternary-operator.


    Code (CSharp):
    1. bool debug = true;
    2.  
    3. debug?
    4.     print("Printing in console");

    Is much shorter than if open ( closing ) moving with arrows, etc. But if this eventually shortcut is done then there will be time lost in the expansion modification. Since when we need to add more lines then we need to make a new if statement. I have no hope and I do not like dialects but but who I am I to judge.

    JAJA LOL Yes, using the original if statement is at the moment the only thing that really works in this case. I try to use the conditional ternary operator adding return and null instead of the empty string with no success. Ryiah was just showing what was posible to achieve.

    Actually I'm typing only one key. I use a special button keyboard for typing

    if ( printInConsole ) Debug.Log("");
     
    Last edited: Aug 7, 2016
  12. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    its not really that much shorter than doing
    Code (CSharp):
    1. if (Debug)
    2.     print("printing in console");
    Setup your ide properly and it will do the closing brackets and braces for you as well as putting the cursor in a useful spot.
    Less keystrokes dosnt mean better, what is better is what is reads well.
     
  13. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    @OP:

    Advanced programmers focus on code readability. They often sacrifice a little bit of performance to improve readability and maintainability. This is because in modern coding the biggest cost is programmer time, not computer time. This means that you should focus on improving your productivity and productivity of your team. Remember that most of your code is not time-critical. Focus on writing code which is VERY easy to understand and well documented. Focus on performance ONLY when it truly matters.

    Example:

    When writing "if" statements I always write full condition: if (something==true) rather than if (something). Why? Because speed is in both cases the same but the first method is more readable and easier to understand.
     
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Good principle. Bad example. ;)
     
  15. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    Except most people use and are taught the shorter form. Both for true and false.
     
  16. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    I also always write: if (something==false), never: if (!something), for the same reasons. The idea is that your code should read like a book. It should flow from your mouth like a natural language poem. Nothing should be cryptic, unless it must.
     
  17. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    Okay. Let's look at an example using your idea of it reading like a book.

    Code (csharp):
    1. if (timerEnabled == true)
    Code (csharp):
    1. if (timerEnabled)
    How many people would normally read "if timer enabled equals true"? Wouldn't they simply read "if timer enabled"? What you're giving as an example doesn't actually improve readability in the slightest. Once again most people use and are taught the shorter form so claiming the longer one is somehow less "cryptic" is just silly.

    If we were discussing the ternary you might have a point about cryptic because it doesn't resemble anything else in the entire language (despite it being half a century old in the programming world).
     
    Kiwasi likes this.
  18. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    @Ryiah:

    You know that there are far more complex cases of "if" usage. When you evaluate something more sophisticated, using "==true" is more readable. Since it is sometimes better I use it all the time for consistency, even for checking flags.
     
  19. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    Yes, there are far more complex cases. The shorter form of the example you gave is not one of them.

    Right, consistency is important. Which is why you should use the shorter form. Most people expect it.
     
  20. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    Another example, by the way using the exact same reasoning concerning readability, is when you use functions rather than simply variables in the conditional statement.

    Code (csharp):
    1. if (isGameRunning() == true)
    Code (csharp):
    1. if (isGameRunning())
    The former would read as "if [is] game running, [then] do something" whereas the second feels far more clunky to read out loud as it would be "if [is] game running equals true, [then] do something".
     
    Kiwasi likes this.
  21. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    In my studio people will expect my way. ;)

    My way is always more readable because it doesn't hide anything. Everything is explicit: in your face. It doesn't matter that it sometimes looks a bit verbose, like in your examples.
     
  22. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    There are plenty of people who expect it both ways. The key phrase in your sentence is "my studio". Coding guidelines are simply for consistency. They won't necessarily be good or bad ones. Part of being a programmer though is living with the decisions of the higher ups no matter how much you may disagree with them.

    By the way there are tons of discussions revolving around the shorter and longer forms. Either way though an experienced programmer won't be confused by either form.

    http://programmers.stackexchange.com/questions/12807/make-a-big-deal-out-of-true

    My favorite response in that link doesn't have anything to do with the discussion though. :p
     
    AlanMattano and Kiwasi like this.
  23. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    Coding style is named "style" for a reason. Styles are by definition subjective and there is no Ultimate Way.

    "Experienced programmers will not be confused"==true. What if a junior programmer is tasked with debugging my code? :) You are not always working with people who are very competent and experienced. Actually most people are idiots. This is true for many programmers as well. My style is idiot-proof.
     
    Last edited: Aug 7, 2016
  24. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I think we should further this discussion by asking which of the following is better style.

    Code (CSharp):
    1. public GameObject gameObject;
    2.  
    3. ...
    4.  
    5. if (gameObject) ...
    6. if (gameObject == true) ...
    7. if (gameObject != null) ...
    Carry on. ;)
     
    Ryiah and MV10 like this.
  25. ToshoDaimos

    ToshoDaimos

    Joined:
    Jan 30, 2013
    Posts:
    679
    I always write if (object!=null). In C++ null used to be zero which used to be "false", but It's better to be explicit. False doesn't have to be zero. Null doesn't have to be zero or false either.
     
  26. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    The trap is set...
     
  27. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    That's easy; this is better style (imo)
    Code (CSharp):
    1. if (gameObject) ...
    Question 2: What would you do?
    Code (CSharp):
    1. bool IsABigger(int a, int b) {
    2.   // Method 1
    3.   if (a > b) return true;
    4.   else return false;
    5.  
    6.   // Method 2
    7.   return a > b;
    8.  
    9.   // Method 3
    10.   return a > b ? true : false;  
    11. }
     
    Ryiah and Kiwasi like this.
  28. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Method 2 for the toy example. And I'd probably just inline it rather then making it its own method.

    However each of the others have their place if the example becomes less trivial. This is also a legitimate approach on more complex problems:

    Code (CSharp):
    1. bool IsABigger(int a, int b) {
    2.   if (a > b) return true;
    3.   return false;
    4. }
    ;)
     
    MV10 likes this.
  29. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,157
    Were we discussing "style"? That term wasn't brought into the discussion until your post that I am quoting.
     
  30. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    The junior programmers should probably never have been hired if they don't understand "if (isRedundant)" and "if (isRedundant == true)" are the same. Boolean variable naming should imply the full condition with the "has", "is", or "can" leading words. Do you include the "== true" when using myDictionary.TryGet?

    P.S. There are languages where it makes sense to write it all, C# is not one of them.
     
    KelsoMRK, Dave-Carlile, MV10 and 4 others like this.
  31. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    100x this.
    Personally I dislike this style as it implies boolean values for me and not complex objects like gameObjects. As complex objects are either instantiated or not, and not true or false, I prefer:
    Code (CSharp):
    1. if(gameObject != null)
    2. {
    3.     ...
    4. }
     
    Last edited: Aug 8, 2016
  32. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    The problem with if(gameObject) is that it's a hack that Unity's introduced, so it works on all UnityEngine.Object objects, but not "normal" objects. So you get a mix of when you can do it and when you can't.

    I'm fine with languages having "falsey" variables, although I prefer them to not have them. If they're in, though, it needs to be consistent.
     
  33. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    I'm still a bit appalled Unity named a class Object. I'm pulling my hair out using a third-party DLL that has to occasionally use System.Object, and re-using code I originally wrote outside Unity, so "using System" is everywhere instead of "System.Object" to disambiguate. Very annoying.

    lol... this is going to make for a pretty crappy poem:

    Code (csharp):
    1.         [HttpPut("{gameid:int}/{newstatus:int}")]
    2.         public IActionResult UpdateStatus(int gameid, int newstatus, [FromBody] JObject payload)
    3.         {
    4.             loginData = Utilities.CheckLoginToken(payload);
    5.             if (loginData == null) return BadRequest();
    6.             return Ok(
    7.                 DiplomacyRules.Gameplay_UpdateStatus(
    8.                     gameid, loginData.Item1.id,
    9.                     newstatus, configuration["GameMapsPath"]));
    10.         }
    11.  
     
    Kiwasi and ericbegue like this.
  34. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    To make everyone happy, I would do:
    Code (CSharp):
    1. public GameObject gameObject;
    2. ...
    3. if ( gameObject && gameObject == true && gameObject != false && gameObject != null )
    4. {
    5.    // do something
    6. }
    Also, you're never can be too sure.
     
  35. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Unfortunately "if (gameObject)" is an incomplete conditional statement and ultimately doesn't make sense. It's effectively the same as writing "if cat" or "if dog", which as you can see aren't actual statements...
     
    Last edited: Aug 8, 2016
    Ryiah, passerbycmc and ericbegue like this.
  36. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    It's unfortunate bleed-over from the world of C/C++ in which this is routine pointer null reference check syntax.
     
  37. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Indeed. Probably time to spring it.

    Answering the question properly really requires an indepth knowledge of how GameObjects work, what the bool operator is actually doing, and how Unity handles ==. While it looks like a style question, it really isn't, there are fundamental differences between if(gameObject) and if(gameObject != null).

    if(gameObject) will check if a GameObject exists and has not been destroyed. Ideally it would have been named GameObject.isNullOrDestroyed instead.

    if(gameObject != null) also checks if a GameObject exists or is destroyed. However a destroyed GameObject is not null. This only works because Unity cheated and overidded the == operator. It's actually misleading, you are getting different behaviour to what you actually typed.

    To make matters worse, the overriden == operator is not called in all situations. Especially when using generics or interfaces. So if(gameObject != null) can sometimes return true even if the object has been destroyed. if(gameObject) will throw a compile time error in the same situation.

    Put all together I prefer the if(gameObject) form. It's a subtle difference, but worth the reduction in bugs.
     
    AlanMattano, Ryiah and Timelog like this.
  38. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Thanks to ILSpy for this post!

    The implementation of UnityEngine.Object's == is:

    Code (csharp):
    1. public static bool operator ==(Object x, Object y)
    2. {
    3.     return Object.CompareBaseObjects(x, y);
    4. }
    The implementation of the implicit bool cast that's used when you do if(gameObject) is:

    Code (csharp):
    1. public static implicit operator bool(Object exists)
    2. {
    3.     return !Object.CompareBaseObjects(exists, null);
    4. }
    Object.CompareBaseObjects is:

    Code (csharp):
    1. private static bool CompareBaseObjects(Object lhs, Object rhs)
    2. {
    3.     bool flag = lhs == null; //This is probably ILSpy messing up, as this would cause an infinite loop. There's probably a ReferenceEquals here irl. I can't see any reason why == would not dispatch to Object.==, which calls this method. Or am I being dumb?
    4.     bool flag2 = rhs == null;
    5.     if (flag2 && flag)
    6.     {
    7.         return true;
    8.     }
    9.     if (flag2)
    10.     {
    11.         return !Object.IsNativeObjectAlive(lhs);
    12.     }
    13.     if (flag)
    14.     {
    15.         return !Object.IsNativeObjectAlive(rhs);
    16.     }
    17.     return lhs.m_InstanceID == rhs.m_InstanceID;
    18. }
    This means that if(go) and if(go != null) is equal in all situations, except when go declared as System.object or ISomeInterface. In that case, if(go) won't compile, and if(go != null) will give false negatives when go is a UnityEngine.Object.

    So in that sense, if(go) is "safer" in that if you write it and it messes up, you know why.
     
    Kiwasi and Timelog like this.
  39. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    The IL instructions are correct even though ILSpy is showing a UnityEngine.Object equality comparison.

    For anyone that is interested:
    Code (csharp):
    1. ldarg.0
    2. ldnull
    3. ceq //direct null reference comparison
    4. stloc.0
    5. ldarg.1
    6. ldnull
    7. ceq //direct null reference comparison
    8. stloc.1
    9. ldloc.1
    10. brfalse   14 (0018) ldloc.1
    11. ldloc.0
    12. brfalse   14 (0018) ldloc.1
    13. ldc.i4.1
    14. ret
    15. ldloc.1
    16. brfalse   21 (0028) ldloc.0
    17. ldarg.0
    18. call      bool UnityEngine.Object::IsNativeObjectAlive(class UnityEngine.Object)
    19. ldc.i4.0
    20. ceq
    21. ret
    22. ldloc.0
    23. brfalse   28 (0038) ldarg.0
    24. ldarg.1
    25. call      bool UnityEngine.Object::IsNativeObjectAlive(class UnityEngine.Object)
    26. ldc.i4.0
    27. ceq
    28. ret
    29. ldarg.0
    30. ldfld     int32 UnityEngine.Object::m_InstanceID
    31. ldarg.1
    32. ldfld     int32 UnityEngine.Object::m_InstanceID
    33. ceq
    34. ret
     
    Last edited: Aug 8, 2016
    AlanMattano and Kiwasi like this.