Skip to content

Commit ea9be74

Browse files
committed
Fix DataRowExtensions.Field for nullable types
Fixes dotnet/corefx#41879 Commit migrated from dotnet/corefx@f664740
1 parent 26970f6 commit ea9be74

2 files changed

Lines changed: 37 additions & 17 deletions

File tree

src/libraries/System.Data.Common/src/System/Data/DataRowExtensions.cs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,25 +147,30 @@ private static class UnboxT<T>
147147

148148
private static Converter<object, T> Create()
149149
{
150-
if (default(T) == null)
151-
return ReferenceOrNullableField;
152-
else
153-
return ValueField;
154-
}
150+
if (typeof(T).IsValueType)
151+
{
152+
return typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>)
153+
? (Converter<object, T>)Delegate.CreateDelegate(
154+
typeof(Converter<object, T>),
155+
typeof(UnboxT<T>)
156+
.GetMethod("NullableField", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
157+
.MakeGenericMethod(typeof(T).GetGenericArguments()[0]))
158+
: ValueField;
159+
}
155160

156-
private static T ReferenceOrNullableField(object value)
157-
{
158-
return ((DBNull.Value == value) ? default(T) : (T)value);
161+
return ReferenceField;
159162
}
160163

164+
private static T ReferenceField(object value)
165+
=> value == DBNull.Value ? default : (T)value;
166+
161167
private static T ValueField(object value)
162-
{
163-
if (DBNull.Value == value)
164-
{
165-
throw DataSetUtil.InvalidCast(SR.Format(SR.DataSetLinq_NonNullableCast, typeof(T)));
166-
}
167-
return (T)value;
168-
}
168+
=> value == DBNull.Value
169+
? throw DataSetUtil.InvalidCast(SR.Format(SR.DataSetLinq_NonNullableCast, typeof(T)))
170+
: (T)value;
171+
172+
private static Nullable<TElem> NullableField<TElem>(object value) where TElem : struct
173+
=> value == DBNull.Value ? default : new Nullable<TElem>((TElem)value);
169174
}
170175
}
171176
}

src/libraries/System.Data.DataSetExtensions/tests/System/Data/DataRowExtensionsTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,23 @@ public void Field_ColumnVersion_NullColumnThrows()
9494
AssertExtensions.Throws<ArgumentNullException>("column", () => DataRowExtensions.Field<int>(row, column: null, version: DataRowVersion.Default));
9595
}
9696

97+
[Fact]
98+
public void Field_Nullable_Enum()
99+
{
100+
DataTable table = new DataTable("test");
101+
table.Columns.Add(new DataColumn("col", typeof(int)));
102+
DataRow row = table.NewRow();
103+
row["col"] = 0;
104+
table.Rows.Add(row);
105+
106+
Assert.Equal(SomeEnum.Foo, table.Rows[0].Field<SomeEnum?>("col"));
107+
}
108+
109+
enum SomeEnum
110+
{
111+
Foo
112+
}
113+
97114
[Fact]
98115
public void SetField_IndexValue_NullRowThrows()
99116
{
@@ -170,7 +187,5 @@ public void SetField_ColumnValue_NullValueReplacedByDBNull()
170187
DataRowExtensions.SetField<string>(row, column: column, value: null);
171188
Assert.Equal(DBNull.Value, row[column]);
172189
}
173-
174-
175190
}
176191
}

0 commit comments

Comments
 (0)