.NET:如何获得null对象的Type?

Cod*_*ike 31 .net c# types gettype

我有一个带out参数的方法,尝试进行类型转换.基本上:

public void GetParameterValue(out object destination)
{
    object paramVal = "I want to return this. could be any type, not just string.";

    destination = null; // default out param to null
    destination = Convert.ChangeType(paramVal, destination.GetType());
}
Run Code Online (Sandbox Code Playgroud)

问题是,通常会有人称之为:

string output;
GetParameterValue(output);
Run Code Online (Sandbox Code Playgroud)

这将失败,因为:

destination.GetType()
Run Code Online (Sandbox Code Playgroud)

destination为null,因此我们无法调用.GetType()它.我们也不能打电话:

typeof(destination)
Run Code Online (Sandbox Code Playgroud)

因为destination是变量名而不是类型名.

那么有没有办法获得设置为null的对象的类型?我认为必须有一种方法可以知道什么类型的存储位置没有分配任何东西.


只是为了提供更多信息,我试图创建一个实用程序方法来获取Oracle存储过程的输出参数.问题是DbParameter.Value对象类型.

对于开发人员来说,最理想的是:

string val = GetParameterValue("parameterName");
Run Code Online (Sandbox Code Playgroud)

值得注意的是,没有类型的铸造.在实践中,你不知道"等于"的lparam,所以我选择了:

string val;
GetParameterValue("parameterName", out val);
Run Code Online (Sandbox Code Playgroud)

在方法中,我会知道输出变量的目标类型.我猜这是一个不好的假设.作为替代方案,我也写了这个方法:

public T GetParameterValue<T>(string paramName)
Run Code Online (Sandbox Code Playgroud)

所以开发人员可以这样做:

string val = GetParameterValue<string>("parameterName");
Run Code Online (Sandbox Code Playgroud)

我发现显式的"字符串"声明是重复的,特别是因为在实践中,目标可能是对象属性和oracle数据类型可能会改变(想想ORM):

MyObj.SomeProp = GetParameterValue<MyObj.SomeProp.GetType()>("parameterName");
Run Code Online (Sandbox Code Playgroud)

但同样,如果MyObj.SomeProp为null,则该.GetType()调用失败.VM必须知道它的类型MyObj.SomeProp,即使它是null,对吗?或者它会如何捕获强制转换异常?


为了部分解决我自己的问题,我可以这样做:

MyObj.SomeProp = GetParameterValue<typeof(MyObj).GetField("SomeProp").GetType()>("parameterName");
Run Code Online (Sandbox Code Playgroud)

整个想法是不必在多个地方显式使用Type,因此如果数据类型发生更改,则只需在目标对象(MyObj.SomeProp)和数据库中进行更改.一定有更好的方法...

Mar*_*iep 32

那么有没有办法获得设置为null的对象的类型?我认为必须有一种方法可以知道什么类型的存储位置没有分配任何东西.

不必要.你可以说最好的是它是一个object.甲null参考不指向任意存储位置,所以没有元数据从其中可以作出这样的判定.

您可以做的最好的事情是将其更改为更通用,如:

public void GetParameterValue<T>(out T destination)
{
    object paramVal = "Blah";
    destination = default(T);
    destination = Convert.ChangeType(paramVal, typeof(T));
}
Run Code Online (Sandbox Code Playgroud)

T可以推断出类型,因此您不需要显式地为方法提供类型参数.


Dam*_*ell 9

如果您不介意将方法声明为通用方法,则可能会出现这种情况.试试这个.

class Program
{
    public static void GetParameterValue<T>(out T destination)
    {
        Console.WriteLine("typeof(T)=" + typeof(T).Name);
        destination = default(T);
    }
    static void Main(string[] args)
    {
        string s;
        GetParameterValue(out s);
        int i;
        GetParameterValue(out i);
    }
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*yer 7

以下扩展方法返回其声明的参数类型,无论其内容如何:

using System;

namespace MyNamespace
{
    public static class Extensions
    {
        /// <summary>
        /// Gets the declared type of the specified object.
        /// </summary>
        /// <typeparam name="T">The type of the object.</typeparam>
        /// <param name="obj">The object.</param>
        /// <returns>
        /// A <see cref="Type"/> object representing type 
        /// <typeparamref name="T"/>; i.e., the type of <paramref name="obj"/> 
        /// as it was declared. Note that the contents of 
        /// <paramref name="obj"/> are irrelevant; if <paramref name="obj"/> 
        /// contains an object whose class is derived from 
        /// <typeparamref name="T"/>, then <typeparamref name="T"/> is 
        /// returned, not the derived type.
        /// </returns>
        public static Type GetDeclaredType<T>(
            this T obj )
        {
            return typeof( T );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由于这是一个扩展方法,因此其参数可以是空引用,并且以下所有方法都可以正常工作:

string myString = "abc";
object myObj = myString;
Type myObjType = myObj.GetDeclaredType();

string myNullString = null;
object myNullObj = myNullString;
Type myNullObjType = myNullObj.GetDeclaredType();
Run Code Online (Sandbox Code Playgroud)

请注意,myObjTypemyNullObjType都将被设置为System.Object的,而不是System.String.

如果你真的想要obj的内容类型,当它不是null时,那么将return行更改为:

return (obj != null) ? obj.GetType() : typeof( T );
Run Code Online (Sandbox Code Playgroud)