Perché il seguente frammento dovrebbe essere un problema per l'inferenza di tipo C # 2.0?

StackOverflow https://stackoverflow.com/questions/1023345

  •  06-07-2019
  •  | 
  •  

Domanda

Sono al capitolo 9 di CSharp in profondità di Jon Skeet in una sezione che spiega i miglioramenti apportati all'inferenza di tipo in 3.0

Esiste un frammento di codice su Pg.247 che "non dovrebbe essere compilato con 2.0" - Tuttavia non riesco a trovare un motivo per cui non dovrebbe. Ho provato il problema con VS2008 C # Express Edition su un progetto con framework di destinazione come 2.0 - tutte e tre le chiamate seguenti vengono compilate ed eseguite anche .

2.0 ha introdotto la possibilità di inferire il giusto tipo di delegato.

new List<ThreadStart>().Add( delegate { Console.WriteLine("New Thread!"); } );   // works

Ovviamente Jon non può sbagliarsi (;) 'Sql is broken' + non c'è menzione di questo nella pagina errata del libro.) Quindi il mio principale sospetto sarebbe che stia ancora usando l'inferenza di tipo 3.0 - Cosa mi sto perdendo?

    delegate int MyDelegate(string s);
    delegate TOutput MyConverter<TInput, TOutput>(TInput input);
    static void MyParse(MyDelegate del)
    {
        Console.WriteLine(del("100"));
    }
    static void MyConvert<TInput, TOutput>(MyConverter<TInput, TOutput> del, TInput input)
    {
        Console.WriteLine(del(input));
    }

    // Jon's code snippet begin
    delegate T MyFunc<T>();
    static void WriteResult<T>(MyFunc<T> function)
    {
        Console.WriteLine(function());
    }
    // end

    static void Main(string[] args)
    {
        MyParse(delegate(string s)
            {
                return Int32.Parse(s);
            }
        );
        MyConvert(delegate(string s)
            {
                return Int32.Parse(s);
            },
            "100");
        WriteResult(delegate { return 5; });    // Jon: Shouldn't work.
    }
È stato utile?

Soluzione

Ciò che fa l'impostazione "framework di destinazione" è disabilitare le librerie e i metodi che sono stati aggiunti nelle versioni più recenti del framework. La maggior parte delle nuove funzionalità linguistiche non richiede un supporto runtime speciale o nuove librerie. Quindi, se li usi, hai bisogno del compilatore più recente, ma la tua app funzionerà ancora su 2.0.

Altri suggerimenti

Ho Visual Studio 2005 installato sul mio computer e ho appena provato il codice che hai pubblicato.

Sia MyConvert che WriteResult non funzionano. Ottengo i seguenti errori:

The type arguments for method 'ConsoleApplication1.Program.MyConvert<TInput,TOutput>(ConsoleApplication1.Program.MyConverter<TInput,TOutput>, TInput)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

e

The type arguments for method 'ConsoleApplication1.Program.WriteResult<T>(ConsoleApplication1.Program.MyFunc<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Non ho la mia copia del libro di Jon, ma probabilmente arriverà presto!

In quale sezione si trova? Prova a cercarlo qui: http://csharpindepth.com/Notes.aspx

MODIFICA: In realtà, il targeting della versione del framework non ha nulla a che fare con la versione del compilatore. Quindi stai ancora usando C # 3.0. Il compilatore deve solo capire quale IL generare, in modo che possa funzionare su CLR 2.0, e quindi può eseguire tutta l'inferenza che gli piace fare.

Ci sono diverse diverse versioni coinvolte qui:

  • L'IDE: Visual Studio 2008
  • Il framework .NET: ti rivolgi a .NET 2.0
  • Il CLR: stai prendendo di mira 2.0 (ignorando i service pack :)
  • Il compilatore C # che stai utilizzando: Visual Studio 2008 utilizza sempre il compilatore C # 3.0
  • La versione della lingua targetizzata dal compilatore: 3.0 per impostazione predefinita

Per vedere l'inferenza del tipo fallire senza tornare al compilatore versione 2.0, devi fare in modo che il compilatore C # usi la versione 2 del linguaggio. Non so se l'edizione express di Visual Studio lo esponga, ma è possibile utilizzare la riga di comando per vederlo.

Sfortunatamente - e questo è davvero strano - ora non riesco nemmeno a riprodurre la difficoltà in questo modo.

Ecco cosa ho appena provato:

using System;

class Test
{
    public delegate T Function<T>();
    public static T Execute<T>(Function<T> function)
    {
        return function();
    }

    static void Main()
    {
        Execute(delegate { return 5; });
    }
}

Mi aspettavo che la compilazione con

csc /langversion:ISO-2 Test.cs

fallirebbe ... ma non lo è. Questo non riesce con il vero compilatore C # 2:

>c:\Windows\Microsoft.NET\Framework\v2.0.50727\csc Test.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.3053
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

Test.cs(14,9): error CS0411: The type arguments for method
        'Test.Execute<T>(Test.Function<T>)' cannot be
        inferred from the usage. Try specifying the type 
        arguments explicitly.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top