Reputation: 13994
I'm creating a generic method which should be able to return null
.
As an example I've created this method GetSecondSmallest(List<T>)
below. This function loops through all of the IComparable
items and returns the second smallest item if possible. If this item does not exist it returns null
.
public T? GetSecondSmallest<T>(List<T> items) where T : Nullable, IComparable
{
if (items.Count == 0) return null;
T smallest = items[0];
T? secondSmallest = null;
// Find second smallest by looping through list
return secondSmallest;
}
Two example usages of this method would be:
GetSecondSmallest(new List<int> {4, 2, 3, 1, 6, 8}) // Should return 2
GetSecondSmallest(new List<MyComparable> {new MyComparable('x')}) // Should return null
When you try to compile this code you'll see what the problem is here:
Error CS0717 'Nullable': static classes cannot be used as constraints
How can I make this method return either an instance of T
or null
?
EDIT: I have already seen this question, but this does not answer my question, because in my situation the parameter is also generic, and should be Nullable
. So the provided answers there aren't applicable.
Upvotes: 4
Views: 7623
Reputation: 4069
Use a wrapper class such as Tuple to wrap the resulting value. In the example below, null is returned if there is no second smallest item, otherwise a Tuple is returned with the second smallest value.
public static void Main()
{
var result1 = GetSecondSmallest(new List<int>
{
4, 2, 3, 1, 6, 8
}); // Should return 2
var result2 = GetSecondSmallest(new List<MyComparable>
{
new MyComparable('x')
}); // Should return null
Console.WriteLine("result1=" + result1.Item1);
Console.WriteLine("result2 == null: " + (result2 == null));
}
public static Tuple<T> GetSecondSmallest<T>(List<T> items)where T : IComparable
{
return items.Skip(1).Select(v => Tuple.Create(v)).FirstOrDefault();
}
Upvotes: 1
Reputation: 2393
Change the return type to Nullable, and call the method with the non nullable parameter
Simple example:
static void Main(string[] args)
{
int? i = GetValueOrNull<int>(null, string.Empty);
}
public static Nullable<T> GetValueOrNull<T>(DbDataRecord reader, string columnName) where T : struct
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
return (T)columnValue;
return null;
}
Nullable type as a generic parameter possible?
UPD
Like this:
public Nullable<T> GetSecondSmallest<T>(List<T> items) where T : IComparable
{
if (items.Count == 0) return null;
Nullable<T> smallest = items[0];
Nullable<T> secondSmallest = null;
// Find second smallest by looping through list
return secondSmallest;
}
Upvotes: 1
Reputation: 157098
You can't narrow T
down as nullable or an object. You have to make two methods, one for T
and one for T?
.
public T? GetSecondSmallestAsNullable<T>(List<T> items) where T : struct
{
return null;
}
public T GetSecondSmallestAsClass<T>(List<T> items) where T : class
{
return null;
}
Upvotes: 4