Condividi tramite


Ultime modifiche in Visual C# 2010

Nella tabella seguente vengono elencate le modifiche principali in Visual C# 2010 che potrebbero impedire la compilazione di un'applicazione creata in Visual C# 2008 o che potrebbero modificare il comportamento in fase di esecuzione.

Categoria

Problema

Descrizione

Associazione di assembly

L'associazione di assembly tratta due assembly come equivalenti.

Le applicazioni C# 2010 che fanno riferimento contemporaneamente sia alla versione .NET Framework che alla versione .NET Framework per Silverlight di un particolare assembly di riferimento e che utilizzano anche extern alias, provocano errori del compilatore. Per impostazione predefinita, l'associazione di assembly tratta due assembly come equivalenti.

Per risolvere l'errore, utilizzare l'opzione del compilatore /appconfig per specificare il percorso di un file app.config che disabilita il comportamento predefinito tramite il tag <supportPortability>. Per ulteriori informazioni, vedere /appconfig (opzioni del compilatore C#).

Se si esegue la compilazione di un'applicazione tramite Microsoft Build Engine (MSBuild), aggiungere il tag appropriato al file con estensione csproj.

Covarianza e controvarianza

Una nuova conversione implicita è stata aggiunta per le interfacce e i delegati generici come IEnumerable<T> e Func<TResult>.

Le interfacce e i delegati generici come IEnumerable<T> e Func<TResult> dispongono ora di una conversione implicita per gli argomenti di tipo generico. In C# 2010, ad esempio, è possibile convertire IEnumerable<string> in IEnumerable<object> in modo implicito e questo potrebbe comportare un comportamento diverso negli scenari seguenti.

Per ulteriori informazioni, vedere Covarianza e controvarianza (C# e Visual Basic).

Operatore null-coalescing

L'operatore null-coalescing (??) non consente variabili locali non assegnate.

In C# 2010 non è possibile utilizzare variabili locali non assegnate come operandi sul lato destro dell'operatore null-coalescing, anche se l'operando sul lato sinistro è sicuramente diverso da null.

Il codice seguente consente ad esempio la compilazione in C# 2008, ma produce un Errore del compilatore CS0165 in C# 2010.

int? i;
int? j;
int? x = (i = 2) ?? j;

Inferenza del tipo del gruppo di metodi

Il compilatore è in grado di dedurre i delegati sia generici che non generici per i gruppi di metodi e questo potrebbe comportare ambiguità.

In C# 2008 il compilatore non è in grado di dedurre i delegati generici per i gruppi di metodi. Di conseguenza, viene sempre utilizzato un delegato non generico, se disponibile.

In C# 2010 vengono dedotti sia i delegati generici che non generici per i gruppi di metodi e la probabilità di inferenza di entrambi da parte del compilatore è equivalente. Questo può comportare ambiguità se sono presenti sia versioni generiche che non generiche di un delegato ed entrambe soddisfano i requisiti. Il codice seguente consente, ad esempio, la compilazione in C#2008 e chiama un metodo che utilizza un delegato non generico. In C# 2010 questo codice provoca un errore del compilatore che segnala una chiamata ambigua.

public class Sample
{
    delegate string NonGenericDelegate();
    delegate T GenericDelegate<T>();
    string UseDelegate(NonGenericDelegate del)
    {
        return null;
    }

    T UseDelegate<T>(GenericDelegate<T> del)
    {
       return default(T);
    }

    public string Test()
    {
       // This line produces 
       // a compiler error in C# 2010.
       return UseDelegate(Test);
    }
}

Parametri facoltativi

C# è ora in grado di riconoscere OptionalAttribute e questo potrebbe comportare modifiche nella risoluzione dell'overload del metodo.

In C# 2008 il compilatore ignora OptionalAttribute perché in C# non sono supportati i parametri facoltativi.

In C# 2010 vengono introdotti i parametri facoltativi. È possibile dichiarare parametri facoltativi utilizzando la nuova sintassi del linguaggio oppure utilizzando OptionalAttribute. Se si utilizza OptionalAttribute in C# 2008 per garantire l'interoperabilità con altri linguaggi che supportano i parametri facoltativi, ad esempio Visual Basic, in C# 2008 vengono sempre scelti solo i metodi i cui parametri sono tutti elencati nella chiamata al metodo. In C# 2010 può venire selezionato un metodo che dispone di parametri facoltativi, anche se questi parametri non sono specificati nella chiamata al metodo.

Il codice seguente consente di chiamare un metodo da una classe base in C# 2008 perché un attributo facoltativo viene ignorato e il compilatore si comporta come se il metodo nella classe derivata richiedesse sempre un parametro di stringa. In C# 2010 il codice chiama un metodo da una classe derivata perché la firma del metodo corrisponde ora alla chiamata al metodo.

class Program
{
    public static void Main(string[] args)
    {
        var obj = new Derived();
        obj.Method();
    }
}

class Base
{
    public void Method() 
    { 
        Console.WriteLine(
            "Base class + no optional parameters"); 
    }
}

class Derived : Base
{
    public void Method(
        [Optional][DefaultParameterValue("Hello")] 
        string s) 
    { 
        Console.WriteLine(
            "Derived class + an optional parameter");
    }
}
// Prints different results.
// C# 2008: Base class + no optional parameters
// C# 2010: Derived class + an optional parameter

Per ulteriori informazioni, vedere Argomenti denominati e facoltativi (Guida per programmatori C#).

Tipi di interoperabilità incorporati

Il tentativo di creare un'istanza di un tipo COM incorporato utilizzando CoClass provoca un errore del compilatore.

In C# 2010 quando si aggiunge un riferimento a un assembly di interoperabilità, ad esempio Microsoft.Office.Interop.Word o Microsoft.Office.Interop.Excel, i tipi di questo assembly sono incorporati. Per ulteriori informazioni, vedere Procedura dettagliata: incorporamento dei tipi da assembly gestiti (C# e Visual Basic) e /link (opzioni del compilatore C#).

Quando si crea un'istanza di un tipo COM incorporato nel codice, è necessario creare l'istanza utilizzando l'interfaccia appropriata. Se si tenta di creare un'istanza di un tipo COM incorporato utilizzando CoClass, viene segnalato un errore dal compilatore.

// Add the following statement
// at the beginning of the file:
// using Word = Microsoft.Office.Interop.Word;
// This statement does not compile in C# 2010.
Word.Application wordClass = 
    new Word.ApplicationClass();
// Use the following code instead.
Word.Application wordInterface = 
    new Word.Application();

Tipi di interoperabilità incorporati

Non è possibile accedere alle proprietà indicizzate dai metodi get_ e set_.

Quando si incorporano tipi COM, tutte le chiamate agli oggetti COM vengono inviate in modo dinamico. Come illustrato nell'esempio di codice seguente, se si tenta di accedere a una proprietà indicizzata Range mediante il metodo get_Range, il gestore di associazione di runtime C# cerca il metodo get_Range definito dall'utente nella classe e questo metodo non esiste. Per evitare questo problema, utilizzare la sintassi C# 2010 per le proprietà indicizzate. Per ulteriori informazioni, vedere Procedura: accedere agli oggetti di interoperabilità di Office utilizzando le funzionalità di Visual C# 2010 (Guida per programmatori C#).

// Add the following statement
// at the beginning of the file:
// using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
excelApp.Workbooks.Add(
    Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet sheet = 
    excelApp.ActiveSheet as Excel.Worksheet;
// The following statement throws 
// a run-time excpetion in C# 2010.
Excel.Range rangeOld = 
    sheet.get_Range(
        sheet.Cells[1, 1], sheet.Cells[2, 2]);
// Use the following syntax instead.
Excel.Range rangeNew = 
    sheet.Range[sheet.Cells[1, 1], 
                sheet.Cells[2, 2]];

Sincronizzazione di eventi

La sincronizzazione per la scrittura nel campo sottostante di un evento nei metodi di aggiunta e rimozione generati dal compilatore viene ora eseguita utilizzando il metodo CompareExchange. Ciò potrebbe causare una race condition.

In C# 2010 la sincronizzazione per il campo sottostante per i metodi di aggiunta e rimozione generati dal compilatore viene eseguita utilizzando il metodo CompareExchange anziché MethodImplAttribute.

Ciò potrebbe causare situazioni di race condition che non erano presenti in C# 2008, come illustrato nell'esempio di codice seguente.

using System;
using System.Threading;

class Sample
{
    public event Action sampleEvent;

    static void Main()
    {
        new Sample().Loop();
    }

    void Loop()
    {
        new Thread(() => Test.Method(this)).Start();
        while (true)
        {
            lock (this)
            {
                if (sampleEvent != null)
                {
                    // In C# 2010, sampleEvent 
                    // can be null here,
                    // which causes 
                    // a run-time exception.
                    sampleEvent();
                }
            }
        }
    }
}

class Test
{
    public static void Method(Sample arg)
    {
        while (true)
        {
            arg.sampleEvent += Method;
            arg.sampleEvent -= Method;
        }
    }
    static void Method() { }
}

Per evitare la race condition, modificare il metodo Loop come illustrato nell'esempio di codice seguente.

void Loop()
{
   new Thread(() => Test.Method(this)).Start();
   while (true)
   {
       lock (this)
       {
           // Create a local copy of the delegate.
           Action local = sampleEvent;
           if (local != null)
           {
               local();
           }
        }
    }
}

Vedere anche

Altre risorse

Guida introduttiva a Visual C#

MSBuild