일반적인 매개 변수로 널 입력 가능?
나는 이런 식으로하고 싶다 :
myYear = record.GetValueOrNull<int?>("myYear"),
널 입력 가능 유형을 일반 매개 변수로 확인하십시오.
GetValueOrNull
함수가 null을 반환 할 수 있기 때문에 첫 번째 시도는 다음과 같습니다.
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
그러나 지금 내가 얻는 오류는 다음과 같습니다.
'int?'유형 제네릭 형식 또는 메서드에서 매개 변수 'T'로 사용하려면 참조 형식이어야합니다.
권리! Nullable<int>
입니다 struct
! 그래서 클래스 제약 조건을 제약 조건으로 변경하려고 시도했지만 struct
부작용으로 null
더 이상 반환 할 수 없습니다 .
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
이제 과제 :
myYear = record.GetValueOrNull<int?>("myYear");
다음과 같은 오류가 발생합니다.
'int?'유형 일반 유형 또는 메소드에서 매개 변수 'T'로 사용하려면 널 입력 불가능 값 유형이어야합니다.
널 입력 가능 유형을 일반 매개 변수로 지정할 수 있습니까?
반환 유형을 Nullable로 변경하고 nullable이 아닌 매개 변수를 사용하여 메서드를 호출하십시오.
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;
}
public static T GetValueOrDefault<T>(this IDataRecord rdr, int index)
{
object val = rdr[index];
if (!(val is DBNull))
return (T)val;
return default(T);
}
다음과 같이 사용하십시오.
decimal? Quantity = rdr.GetValueOrDefault<decimal?>(1);
string Unit = rdr.GetValueOrDefault<string>(2);
원래 코드에 대해 두 가지 작업을 수행하십시오. where
제약 조건을 제거 하고 마지막을 return
에서 return null
로 변경하십시오 return default(T)
. 이렇게하면 원하는 유형을 반환 할 수 있습니다.
그런데 명령문을 is
로 변경하여 사용을 피할 수 있습니다 .if
if (columnValue != DBNull.Value)
면책 조항 : 이 답변은 효과가 있지만 교육 목적으로 만 사용됩니다. :) James Jones의 솔루션은 아마도 여기에서 가장 좋을 것입니다.
C # 4.0의 dynamic
키워드를 사용하면 안전성이 떨어지더라도 훨씬 쉽게 만들 수 있습니다.
public static dynamic GetNullableValue(this IDataRecord record, string columnName)
{
var val = reader[columnName];
return (val == DBNull.Value ? null : val);
}
이제 RHS에 대한 명시 적 유형 힌트가 필요하지 않습니다.
int? value = myDataReader.GetNullableValue("MyColumnName");
사실, 당신은 전혀 필요하지 않습니다!
var value = myDataReader.GetNullableValue("MyColumnName");
value
이제 int 또는 문자열이거나 DB에서 반환 된 모든 유형이됩니다.
유일한 문제는 이것이 LHS에서 널 입력 불가능 유형을 사용하는 것을 방해하지 않는다는 것입니다.
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot convert null to 'int' because it is a non-nullable value type
사용하는 모든 코드와 마찬가지로 dynamic
:주의 코더.
이것과 비슷한 것을해야했습니다. 내 코드 :
public T IsNull<T>(this object value, T nullAlterative)
{
if(value != DBNull.Value)
{
Type type = typeof(T);
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())
{
type = Nullable.GetUnderlyingType(type);
}
return (T)(type.IsEnum ? Enum.ToObject(type, Convert.ToInt32(value)) :
Convert.ChangeType(value, type));
}
else
return nullAlternative;
}
참조 유형과 구조체 유형을 처리하고 싶다고 생각합니다. XML 요소 문자열을 더 유형이 지정된 유형으로 변환하는 데 사용합니다. 리플렉션을 사용하여 nullAlternative를 제거 할 수 있습니다. formatprovider는 문화에 의존하는 '.'을 처리하는 것입니다. 또는 ','구분 기호 (예 : 10 진수 또는 정수 및 2 배) 이것은 작동 할 수 있습니다 :
public T GetValueOrNull<T>(string strElementNameToSearchFor, IFormatProvider provider = null )
{
IFormatProvider theProvider = provider == null ? Provider : provider;
XElement elm = GetUniqueXElement(strElementNameToSearchFor);
if (elm == null)
{
object o = Activator.CreateInstance(typeof(T));
return (T)o;
}
else
{
try
{
Type type = typeof(T);
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())
{
type = Nullable.GetUnderlyingType(type);
}
return (T)Convert.ChangeType(elm.Value, type, theProvider);
}
catch (Exception)
{
object o = Activator.CreateInstance(typeof(T));
return (T)o;
}
}
}
다음과 같이 사용할 수 있습니다.
iRes = helper.GetValueOrNull<int?>("top_overrun_length");
Assert.AreEqual(100, iRes);
decimal? dRes = helper.GetValueOrNull<decimal?>("top_overrun_bend_degrees");
Assert.AreEqual(new Decimal(10.1), dRes);
String strRes = helper.GetValueOrNull<String>("top_overrun_bend_degrees");
Assert.AreEqual("10.1", strRes);
스레드가 끊겼을 수도 있지만 다음을 사용하는 경향이 있습니다.
public static T? GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
{
return reader[columnName] as T?;
}
방금 같은 문제가 발생했습니다.
... = reader["myYear"] as int?;
작동하고 깨끗합니다.
문제없이 모든 유형에서 작동합니다. 결과가 DBNull 인 경우 변환이 실패하면 null이 반환됩니다.
나는 이것이 오래된 것을 알고 있지만 여기에 다른 해결책이 있습니다.
public static bool GetValueOrDefault<T>(this SqlDataReader Reader, string ColumnName, out T Result)
{
try
{
object ColumnValue = Reader[ColumnName];
Result = (ColumnValue!=null && ColumnValue != DBNull.Value) ? (T)ColumnValue : default(T);
return ColumnValue!=null && ColumnValue != DBNull.Value;
}
catch
{
// Possibly an invalid cast?
return false;
}
}
이제는 T
값 또는 참조 유형인지 상관하지 않습니다 . 함수가 true를 리턴하는 경우에만 데이터베이스에서 합리적인 값을 갖습니다. 용법:
...
decimal Quantity;
if (rdr.GetValueOrDefault<decimal>("YourColumnName", out Quantity))
{
// Do something with Quantity
}
이 방법은 int.TryParse("123", out MyInt);
여러 일반 제약 조건은 OR 방식 (제한 없음)으로 결합 할 수 없으며 AND 방식 (더 제한적)으로 만 결합 할 수 없습니다. 한 가지 방법으로 두 시나리오를 모두 처리 할 수는 없습니다. 또한 일반 제약 조건을 사용하여 메서드에 고유 한 서명을 만들 수 없으므로 두 개의 별도 메서드 이름을 사용해야합니다.
그러나 일반 제한 조건을 사용하여 메소드가 올바르게 사용되는지 확인할 수 있습니다.
필자의 경우 특히 null이 반환되기를 원했지만 가능한 값 유형의 기본값은 절대로 사용하지 않았습니다. GetValueOrDefault = 잘못되었습니다. GetValueOrNull = 양호
"Null"과 "Nullable"이라는 단어를 사용하여 참조 유형과 값 유형을 구분했습니다. 그리고 여기 System.Linq.Enumerable 클래스의 FirstOrDefault 메소드를 보완하는 몇 가지 확장 메소드의 예가 있습니다.
public static TSource FirstOrNull<TSource>(this IEnumerable<TSource> source)
where TSource: class
{
if (source == null) return null;
var result = source.FirstOrDefault(); // Default for a class is null
return result;
}
public static TSource? FirstOrNullable<TSource>(this IEnumerable<TSource?> source)
where TSource : struct
{
if (source == null) return null;
var result = source.FirstOrDefault(); // Default for a nullable is null
return result;
}
참고 URL : https://stackoverflow.com/questions/209160/nullable-type-as-a-generic-parameter-possible
'IT' 카테고리의 다른 글
자식 저장소 크기 줄이기 (0) | 2020.03.30 |
---|---|
URL 또는 웹 페이지의 Google 캐시 기간을 어떻게 알 수 있습니까? (0) | 2020.03.30 |
엔터티 프레임 워크 및 연결 풀링 (0) | 2020.03.30 |
Maven 종속성 검색을 위해 Eclipse에서 색인 다운로드를 사용하려면 어떻게해야합니까? (0) | 2020.03.30 |
루비의 블록 및 수율 (0) | 2020.03.30 |