Hoe kan ik NULL retourneren van een generieke methode in C#?

Ik heb een generieke methode met deze (dummy) code (ja ik weet dat IList predikaten heeft, maar mijn code gebruikt geen IList maar een andere verzameling, dit is in ieder geval niet relevant voor de vraag…)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

Dit geeft me een bouwfout

“Kan null niet converteren naar typeparameter
‘T’ omdat het een waardetype kan zijn.
Overweeg om in plaats daarvan ‘default(T)’ te gebruiken.”

Kan ik deze fout vermijden?


Antwoord 1, autoriteit 100%

Twee opties:

  • Retourneer default(T), wat betekent dat u nullretourneert als T een referentietype is (of een waarde met een null-waarde), 0voor int, '\0'voor char, enz. (Tabel met standaardwaarden (C#-referentie))
  • Beperk T om een ​​referentietype te zijn met de where T : classbeperking en retourneer vervolgens nullzoals normaal

Antwoord 2, autoriteit 10%

return default(T);

Antwoord 3, autoriteit 4%

U kunt uw beperkingen gewoon aanpassen:

where T : class

Dan is het retourneren van null toegestaan.


Antwoord 4

Voeg de klassebeperking toe als de eerste beperking aan uw generieke type.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

Antwoord 5

  1. Als je een object hebt, moet je typen

    return (T)(object)(employee);
    
  2. als u null moet retourneren.

    return default(T);
    

Antwoord 6

Hieronder staan ​​de twee opties die u kunt gebruiken

return default(T);

of

where T : class, IThing
 return null;

Antwoord 7

Uw andere optie zou zijn om dit toe te voegen aan het einde van uw aangifte:

   where T : class
    where T: IList

Op die manier kun je null retourneren.


Antwoord 8

oplossing van TheSoftwareJedi werkt,

je kunt het ook archiveren met een paar waarde- en nullable-typen:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}

Antwoord 9

Voor de volledigheid is het goed om te weten dat u dit ook kunt doen:

return default;

Het geeft hetzelfde terug als return default(T);


Antwoord 10

Neem de aanbeveling van de fout… en gebruiker default(T)of new T.

Je moet een vergelijking in je code toevoegen om er zeker van te zijn dat het een geldige overeenkomst was als je die route volgt.

Overweeg anders mogelijk een uitvoerparameter voor “overeenkomst gevonden”.


Antwoord 11

Hier is een werkend voorbeeld voor Nullable Enum-retourwaarden:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}

Antwoord 12

Vanwege IThing is de interface niet mogelijk om null te gebruiken. U moet dus standaard(T) gebruiken om de standaardwaarde voor het werkelijke type T te bepalen, dat is gedefinieerd voordat de functie wordt aangeroepen.

using System;
using System.Collections.Generic;
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        IThing x = new List<Thing>().FindThing(1);
    }
}
public static class Ext {
    public static T FindThing<T>(this IList<T> collection, int id) where T : IThing, new()
    {
        foreach (T thing in collection)
        {
            if (thing.Id == id) return (T)thing;
        }
        //return null; //not work
        //return (T)null; //not work
        //return null as T; //not work
        return default(T); //work
    }
}
public interface IThing { int Id {get; set;} }
public class Thing : IThing { public int Id {get;set;}}

Antwoord 13

Nog een alternatief voor de twee hierboven gepresenteerde antwoorden. Als u uw retourtype wijzigt in object, kunt u nullretourneren, terwijl u tegelijkertijd de niet-null-retour cast.

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

Other episodes