Can't write an expression-bodied function member
Asked Answered
P

2

6

NOTE: This appears to be a problem with the compiler that's used with SSDT projects, it's apparently fixed in the 2017 RC. My problem is similar to one described here.

I've got some code which refuses to let me write it as an expression-bodied function member. In short, I want to do this:

void foo() => bar();

But the IDE throws a tantrum and demands I write it like this:

void foo() { bar(); }

I mean sure, it's two extra characters but I'm not sure why it's complaining, the errors don't make sense either. It gives me the following 3 errors:

  • CS0000: ; expected
  • CS0000: Method must have a return type.
  • CS0000: Identifier expected.

The full code looks like this.

public static void foo() => bar("some param"); // Errors on this line.
static void bar(string myParam) { //20 lines of code } 

I've tested this in the C# interactive window and everything compiles and runs correctly. I can't find any unprintable characters in the code.

This is using VS 2015 community with the target framework being 4.6.1

Full code:

using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class Triggers
{

    private const string ConnectionString = "context connection = true";

    private const string ReadInsertedTable = @"
    SELECT ID,
           (
               SELECT *
               FROM inserted AS b
               WHERE a.ID = b.ID
               FOR XML RAW, ELEMENTS XSINIL
           )
    FROM inserted AS a
";
    [SqlTrigger(Name = "Person_Insert", Target = "Person", Event = "FOR INSERT")]
    public static void Person_Insert() => AuditInsert(TableName); //  All errors here.

    private const string TableName = "Person";

    private static void AuditInsert(string tableName)
    {

        using (var readConnection = new SqlConnection(ConnectionString))
        using (var writeConnection = new SqlConnection(ConnectionString))
        {
            using (var readCommand = new SqlCommand(ReadInsertedTable, readConnection))
            {
                readConnection.Open();
                using (var reader = readCommand.ExecuteReader())
                {
                    SqlContext.Pipe.Send((reader));
                }
            }
        }
    }
}

enter image description here

Update: Code compiles using the msbuild utility but still fails in Visual Studio.

Palatinate answered 4/2, 2017 at 7:44 Comment(5)
I have copied your code to my vs and it compiled without errorsArsphenamine
Any idea where to even start looking to try and fix this? Because CS0000 doesn't even seem to be a normal code. I'll add an image from my IDE.Palatinate
what version of VS are you using? note that expression bodied members is feature of C#6 so it does not work on old IDEsTithing
VS2015 Community w/ Update 3.Palatinate
It's important that you mention in which enviroment you're working. In a Visual Studio 2015/2017 you can add the new compiler features to the project via NUGET package manager -> Manage Packages for Solution. Open it and browse for Microsoft.Net.Compilers. Then add it to the project and click INSTALL. Do the same for Microsoft.CodeDom.Providers.DotNetCompilerPlatform. Close NUGET and rebuild your project.Costumier
R
5

This will have something to do with Roslyn. Try to run this:

Non-roslyn: https://dotnetfiddle.net/LJm1Fj

Roslyn: https://dotnetfiddle.net/aMUsj0

I suspect there's something wrong either with your project file or your Visual Studio installation because VS2015 should use Roslyn-based compiler by default.

I'd try:

  • creating a new project with the code from the fiddle above
  • if it compiles then compare the differences in the *.csproj files, mainly the ToolsVersion <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> and targets <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  • you should also look in the Output->Build window in VS and check out the executable being launched, in my case: C:\Program Files (x86)\MSBuild\14.0\bin\csc.exe /noconfig /nowarn:1701,1702,2008 /nostdlib+ /platform:anycpu32bitpreferred /errorreport:prompt /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva+ /reference:"C:\Program Files (x86)\Reference ... Using shared compilation with compiler from directory: C:\Program Files (x86)\MSBuild\14.0\bin
  • if it doesn't compile, I'd suggest reinstalling .NET and VS
Remittee answered 4/2, 2017 at 9:36 Comment(11)
Looks like it's using an old compiler. The csc.exe I'm getting is under C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe. Any idea how to change it?Palatinate
Have you tried to create the vanilla project as I suggested? I think there will be some differences in the project file, presumably in the targets section. Or maybe there is a specific language version set in the project file (Project properties -> Build -> Advanced -> Language Version).Remittee
Yeah, I've just done that. It's to do with the project type. Apparently SQL Server Database Projects' (SSDT) don't use Roslyn.Palatinate
Yep, that's the answer. Either try to merge it with the vanilla c# project template or just use a clean c# project. I don't know what's so specific about SSDT project but if you really need to use it, try extracting the aforementioned logic to a "pure c#" project.Remittee
I'll look into it later. I don't mind compiling and deploying this from the command line. :-) Thanks again.Palatinate
;) Glad to helpRemittee
@Palatinate What do you see when you do as in rocky's first comment, that is Project properties -> Build -> Advanced -> Language Version? Does the dropdown have only versions up to C# 5.0 for your project type?Jedjedd
I don't have Advanced under Build with an SSDT project.Palatinate
@Palatinate I can reproduce what you see! If I create a new project, and choose "SQL Server Database Project", it creates a .sqlproj file, not a .csproj file. If in that SSDT project I add a new item and choose "SQL CLR C#" "Class", and in the resulting C# file use any C# 6.0 feature (also tried with an auto-property with initializer, int P { get; set; } = 42;), I get strange errors when I try to "Build Solution (F6)".Jedjedd
That's pretty much what I did except I did a SQL CLR C# Trigger instead of a class.Palatinate
I've put a link to that question at the top of my question. Thanks though.Palatinate
J
0

This answer turned out to be largely irrelevant.

As the asker figured out himself, with help from user rocky, the issue is that an SQL Server Database Project (.sqlproj) (unlike other projects of type .csproj) is not built with the new C# 6.0 compiler, at least not in Visual Studio 2015. The thread linked by the asker, Usage of wrong compiler during SQL Server Database Project building, has some details.


Old answer:

In your image, the constant declaration:

private const string TableName = "Person";

is missing. However, you have not removed the tableName parameter from the AuditInsert method.

Jedjedd answered 4/2, 2017 at 9:49 Comment(3)
The code is fine, this appears to be a problem with the compiler used for SSDT projects. Apparently it's fixed in the 2017 RC, but I won't be installing that anytime soon. :-)Palatinate
@Palatinate How can AuditInsert(TableName) be fine when there is no TableName defined anywhere? I am looking at your image.Jedjedd
The image was just to show that the errors appeared since Maksim said it compiled fine for him. We've already established it's a compiler issue, not a code one. I'm updating my main question accordingly with a link to a related question.Palatinate

© 2022 - 2024 — McMap. All rights reserved.