Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

C# 7 support?

Discussion in '2018.1 Beta' started by Dejavu2017, Jan 14, 2018.

  1. Dejavu2017

    Dejavu2017

    Joined:
    Sep 29, 2017
    Posts:
    14
    It's great that 2018.1 comes with netstandard 2.0 support. And there was mentioning about using Roslyn as the new compiler that comes with the latest Mono runtime (even though I'm not sure which Mono runtime version comes with 2018.1, even though we are mostly referring to .NET runtime, i.e. 4.6 or netstandard 2.0).

    I did a quick look at the new 2018.1.02b, the C# language version seems to still be locked at "6", and even I change it to "7" in the .csproject "<LangVersion>" section, C# 7 language features like "tuples" would give compiler errors - after restarting Unity3D, I noticed that "LangVersion" is changed back to "6".

    I'm wondering that is it in the roadmap that Unity3D 2018 would bring the latest greatest C# language features or it'll be unfortunately locked at version "6"?
     
    AntonioModer likes this.
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    ValueTuple is available as a nuget package for 4.6.
     
  3. Dejavu2017

    Dejavu2017

    Joined:
    Sep 29, 2017
    Posts:
    14
    ValueTuple is just one example, it's good that there is library support, but I do look forward to the compiler support so I can actually write: `(int, string) x = (0, "");`; and of course other *language* features like out variables, generalized async return type, and even some cutting-edge C# 7.1/7.2 support - such as Span<T> (and of course the runtime support - probably .NET 4.6 is not even capable of that).
     
    IncomeCountry and Freznosis like this.
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Ya compiler support definitely makes most of the new types more interesting. I think Span<T> will go to a nuget package for .net framework, remember hearing that somewhere.
     
  5. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
  6. joncham

    joncham

    Unity Technologies

    Joined:
    Dec 1, 2011
    Posts:
    276
    We can probably increase the C# version supported. It's complicated by fact that currently we use the Mono C# compiler. The plan of the upstream Mono devs was to end of life the Mono compiler at C# 6 (i.e. not implement C# 7+) and migrate to Roslyn.

    However, upstream and us have found that the Roslyn compiler runs noticeably slower than the Mono C# compiler in the context of batch compilation (driving the compiler via command line flags). Roslyn runs faster in a "server" mode where incremental compilation is possible, but the current Roslyn server support is Windows only. We are looking into our own Roslyn server, but it's not complete yet.

    That leaves us with the Mono C# compiler. They are now adding C# 7+ features, but only as time permits and only the more important features. This means we won't have *full* C# 7.x support for a few releases, either via an improved Mono compiler or a faster Roslyn compiler.
     
  7. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Mono compiler from 2018.1b2 supports some C# 7.x features when langversion option is set to experimental.

    1. Expression-bodied everything
    2. Tuples
    3. In-place out variable declaration
    4. Ref-returns and ref-locals
    5. Throw expression

    No compilation errors here:
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. public class Foo
    5. {
    6.     public int bar;
    7.     public int Bar { get => bar; set => bar = value; }
    8.     public Foo(int bar) => this.bar = bar;
    9.     ~Foo() => Debug.Log("Bye!");
    10.     public (int number, string text) GetTuple() => (5, "cinco");
    11.     public void TupleTest()
    12.     {
    13.         var t = GetTuple();
    14.         var (a, b) = t;
    15.         var c = t.number;
    16.     }
    17.     public void OutVarTest()
    18.     {
    19.         if (int.TryParse("42", out var n)) Debug.Log(n);
    20.     }
    21.     public ref int RefReturnTest(ref int a, ref int b)
    22.     {
    23.         if (a > b)
    24.         {
    25.             return ref a;
    26.         }
    27.         return ref b;
    28.     }
    29.     public int RefLocalTest(int a, int b)
    30.     {
    31.         ref int max = ref RefReturnTest(ref a, ref b);
    32.         return max;
    33.     }
    34.     public int ThrowTest(int x) => x > 0 ? 42 : throw new InvalidOperationException();
    35. }
     
  8. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    I'd really like to see C#7 features as well, I'm so used to them by now.
    Thanks a lot for explaining the situation joncham!

    I'll try alexzzzz's workaround in the meantime :)
     
  9. Silktrader

    Silktrader

    Joined:
    Aug 27, 2014
    Posts:
    8
    I'd love "tuples" to work but, with 2018.1.b3, when I set "<LangVersion>4</LangVersion>" to "experimental" or "7", I get the following error: " error CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification".

    I set the runtime to be "Experimental (4.6 Equivalent)", the backend is Mono and the API compatibility level is "Standard 2.0" (I have the same issues with 4.6).
     
  10. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    There are two places where you would want to change language version.

    1. Mono C# compiler options:

    mcs.PNG

    This can be done via .rsp file. Create such a file inside Assets folder:
    Code (Assets/mcs.rsp):
    1. -langversion:experimental
    It's enough to compile code with some C# 7.x features in Unity.

    2. .csproj files generated for Visual Studio: <LangVersion>...</LangVersion>

    This setting specifies the language version for Microsoft C# compiler that is used in Visual Studio. The latest compiler and the latest Visual Studio currently support the following options:

    csc.PNG

    PS
    If you add mcs.rsp to the project, recent versions of Visual Studio Tools for Unity will add <CompilerResponseFile> element in the .csproj files.

    vstu.PNG

    As a result, this "-langversion:experimental" will be passed to Microsoft C# compiler which doesn't understand "experimental". You will get an error when try to compile the code in VS:

    vs.PNG

    You will have to delete <CompilerResponseFile> from .csproj files.
     
    Last edited: Jan 22, 2018
  11. Silktrader

    Silktrader

    Joined:
    Aug 27, 2014
    Posts:
    8
    Thanks for the explanation, @alexzzzz .

    As you say, the mcs "rsp" directive seems to do to the trick — I was able to compile, run scripts with tuples and whatnot.

    Unfortunately, despite my continuous editing "LangVersion" and "CompilerResponseFile", the .csproj files keep getting reset to their initial state. Using the "Open C# Project" (from Unity's Assets menu), or double clicking on C# scripts seems to overwrite the edits. I rely on VS 2017 and Resharper for debugging purposes, so I really need to be able to build from there.

    I am glad for the help, really. I am going to patiently wait until C#7 support is mainstreamed.
     
  12. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    that's because Unity will create .csproj from scratch.

    there is a hidden (undocumented) message that you can implement to intercept that:
    Code (CSharp):
    1. public class MyAssetProcessor : AssetPostprocessor
    2. {
    3.     static void OnGeneratedCSProjectFiles()
    4.     {
    5.     }
    6. }
    you can then open the .csproj and inject the langversion (and delete the CompilerResponseFile element)
     
    MitchAtPG and MechEthan like this.
  13. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    When VSTU is used, it may overwrite modified .csproj files with its own version. Here is a solution - https://docs.microsoft.com/en-us/visualstudio/cross-platform/customize-project-files-created-by-vstu

    I suspect, Unity Plugin for Rider (or is it Rider Plugin for Unity?) also have that problem since it modifies .csproj files too.

    I have a hack project that integrates the latest Roslyn into Unity and solves this kind of problems automatically. The word hack implies that you'd better know what you are doing and how things work inside. You may use it for fun and at your own risk and if something goes wrong no one is responsible.
     
    Last edited: Jan 22, 2018
    SugoiDev likes this.
  14. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    I've said this a few million times before but I would love, love, love it if Unity would include official support for using Roslyn and make that the default compiler for Windows, and only use the whole custom compiler IL2CPP AOT craziness for iPhone. How about a compromise where you let us use the normal .NET stuff but we have to click Yes on a popup like "I hereby solemnly swear that this is a PC game and I will not try to turn it into an iPhone game a year from now, but if for some reason I do, I also solemnly swear that I will not log onto the forums and complain that Unity should have warned me more that iPhone games have different requirements than PC games"
     
    MaxEden and 2dgame like this.
  15. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    @makeshiftwings
    But (Roslyn vs Mono compiler) and (IL2CPP vs JIT) are completely orthogonal questions, aren't they?
     
  16. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    I'm not really sure; I figured Unity made some custom changes to the Mono compiler to produce IL that works better with IL2CPP but maybe they're completely unrelated. But I believe the main reason that either exist is because they want to keep code compatibility between Windows and iPhone development.
     
  17. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    We've not changed the Mono compiler to produce different IL for IL2CPP. In fact, IL2CPP works with IL produced from any C# compiler, so we can't have any special handling.
     
  18. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    We've looked at Roslyn in-depth. The real problem with it now is compile times. It is significantly slower (at least in batch mode) than the Mono C# compiler. The speed difference makes it not usable now. It does have a pretty nice server mode which only recompiles changes (and is much faster than batch mode). We're working on integrating something like that into Unity now.
     
  19. MechEthan

    MechEthan

    Joined:
    Mar 23, 2016
    Posts:
    166
    This thread is a goldmine of information and useful communication. Thank you joncham, alexzzzz and JoshPeterson !
     
    Krajca and MadeFromPolygons like this.
  20. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    I've been switching back and forth the last year or two using alexzzz's and for me at least the Roslyn compiler always seemed faster and much more stable. Maybe that's changed recently. At the moment though, running in .NET 4.6 mode and using Unity 2017.3 is so incredibly slow and constantly crashing that I find it kind of silly for you guys to be even trying to have real performance metrics on this thing. Slight increase in compiler speed is not worth it if it means staying in "Experimental" release mode for the next three years.
     
  21. DC20500

    DC20500

    Joined:
    Feb 12, 2014
    Posts:
    7
  22. DC20500

    DC20500

    Joined:
    Feb 12, 2014
    Posts:
    7
    Also, when I open csproj in notepad(on Windows OS), it says

    <LangVersion>4</LangVersion>

    How to use C# 6.0? ok forget 7.0 for now. :(
     
  23. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    @DC20500, you need Unity 2017.1 or newer.
     
  24. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,983
    Most useful official communication in ages, thanks :)
     
  25. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    I'm use -langversion:6 switch in mcs file for .net 2.0 and it works fine
    additionally I wrote ScProjFixer that clears csproj files and set langVersion 6 there


    Code (CSharp):
    1. using System;
    2. using System.IO;
    3. using System.Text;
    4. using SyntaxTree.VisualStudio.Unity.Bridge;
    5. using UnityEditor;
    6. using UnityEditor.Compilation;
    7. using UnityEditorInternal;
    8. using UnityEngine;
    9.  
    10. [InitializeOnLoad]
    11. public class CsProjFixer
    12. {
    13.     static CsProjFixer()
    14.     {
    15.         ProjectFilesGenerator.ProjectFileGeneration += FixProj;
    16.         //CompilationPipeline.assemblyCompilationStarted += a => Debug.Log( "[CsProjFixer] - FixProj: " + a );
    17.     }
    18.     private static String FixProj( String name, String content )
    19.     {
    20.         var path = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(name.Substring(0, name.Length-7));
    21.        
    22.         try
    23.         {
    24.             StringBuilder sb = new StringBuilder();
    25.             string line = null;
    26.  
    27.             Boolean isEditor = name.Contains(".Editor");
    28.            
    29.             using (var sr = new StringReader(content))
    30.             {
    31.                 while ((line = sr.ReadLine()) != null)
    32.                 {
    33.                     if (line == "    <LangVersion>4</LangVersion>")
    34.                         sb.AppendLine("    <LangVersion>6</LangVersion>");
    35.  
    36.                     else if (line == "    <Reference Include=\"Boo.Lang\" />")
    37.                     {
    38.                     }
    39.                     else if (line == "    <Reference Include=\"UnityScript.Lang\" />")
    40.                     {
    41.                     }
    42.                     else if ( !String.IsNullOrEmpty(path) && line.StartsWith("    <None Include" ) )
    43.                     {
    44.  
    45.                     }
    46.                     else if (!isEditor)
    47.                     {
    48.                         if (line == "    <Reference Include=\"System.XML\" />")
    49.                         {
    50.                         }
    51.                         else if (line == "    <Reference Include=\"System.Xml.Linq\" />")
    52.                         {
    53.                         }
    54.                         else
    55.                         {
    56.                             sb.AppendLine(line);
    57.                         }
    58.                     }
    59.                     else
    60.                     {
    61.                         sb.AppendLine(line);
    62.                     }
    63.                 }
    64.             }
    65.  
    66.             return sb.ToString();
    67.         }
    68.         catch (Exception ex)
    69.         {
    70.             Debug.LogError        ( "[csProjFixer] - FixProj: Fix Fail for file: " + name );
    71.             Debug.LogException    ( ex );
    72.         }
    73.  
    74.         return content;
    75.     }
    76. }
     
  26. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    for .Net 4.6 -langversion:7 works fine but I do not test there because our project dont work there
     
  27. CodeLiftSleep

    CodeLiftSleep

    Joined:
    Jul 15, 2017
    Posts:
    44
    Why is every version of Unity pretty much a standalone version that breaks various assets/functions used in previous versions? When can we start to expect backwards compatabiltiy with some of these updates? This seems like an incredibly poor design decision to force people to stay stuck with bugs that are fixed in new versions because they are at the mercy of other people and other assets to update their methods, etc.

    I mean could you imagine a similar design decision with game designers? You start a game and get 100+ hours of play in and then they release a patch/new version that fixes bugs but its completely incompatible with old saves...there would literally be a revolt...why is this considered acceptable?
     
  28. OswaldHurlem

    OswaldHurlem

    Joined:
    Jan 6, 2017
    Posts:
    40
    Support for C# 7+ is not particularly urgent for me.
    If Unity's API starts featuring ref returns that will be good for performance, but quite bad for its learning curve.
    I would not like slower compile times very much
     
  29. Dejavu2017

    Dejavu2017

    Joined:
    Sep 29, 2017
    Posts:
    14
    I don't really care about slower compilation time *to start with* - I guess a lot of people would prefer to have C# 7.x support as early as possible, maybe bearing with a slower compilation speed and knowing that this will be fixed in the not too distant future, than having to wait for a perfectly performing C# 7.x roslyn integration (who knows when), but have to be locked at C# 6 indefinitely. Even better, is it possible to provide a configuration in the player settings that gives user a choice of: Mono compiler (C# 6), and Roslyn (C# 7.x), and maybe just remind us that Roslyn would suffer a slower compilation speed, etc. etc.

    How does that sound?
     
  30. Dejavu2017

    Dejavu2017

    Joined:
    Sep 29, 2017
    Posts:
    14
  31. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    I have already use all of it in Unity with .Net 2.0 support
     
  32. Loofou

    Loofou

    Joined:
    Aug 22, 2012
    Posts:
    25
    Hey, I used the above mcs.rsp method on 2018.1b07 for around a week now and everything worked great. Now I updated to 2018b12 and while everything still compiles fine, on running the game or any editor script that uses C# 7 features (like a ref return in my case) Unity throws the exception "InvalidProgramException: Invalid IL code in #functionname# (): IL_003b: stloc.0" (#functionname# is the name of a function that uses a ref return). Like I said, it compiles fine on Mono with .Net 4.6, but does not run. Anyone have any ideas on what's changed?
     
  33. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    3,136
    Could you please file a bug report with a minimal reproduction case and reply with the case #?
    Detailed information about bug reporting can be found here:
    Unity - A guide to beta testing