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

我有一个带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()); } 

问题是通常有人会这样称呼:

 string output; GetParameterValue(output); 

这将失败,因为:

 destination.GetType() 

destination为null,因此我们不能在其上调用.GetType() 。 我们也不能打电话:

 typeof(destination) 

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

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


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

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

 string val = GetParameterValue("parameterName"); 

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

 string val; GetParameterValue("parameterName", out val); 

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

 public T GetParameterValue(string paramName) 

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

 string val = GetParameterValue("parameterName"); 

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

 MyObj.SomeProp = GetParameterValue("parameterName"); 

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


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

 MyObj.SomeProp = GetParameterValue("parameterName"); 

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

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

不必要。 你能说的最好的是它是一个objectnull引用不指向任何存储位置,因此没有元数据可以从中进行确定。

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

 public void GetParameterValue(out T destination) { object paramVal = "Blah"; destination = default(T); destination = Convert.ChangeType(paramVal, typeof(T)); } 

可以推断出T的类型,因此您不需要明确地为方法提供类型参数。

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

 class Program { public static void GetParameterValue(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); } } 

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

 using System; namespace MyNamespace { public static class Extensions { ///  /// Gets the declared type of the specified object. ///  /// The type of the object. /// The object. ///  /// A  object representing type /// ; ie, the type of  /// as it was declared. Note that the contents of ///  are irrelevant; if  /// contains an object whose class is derived from /// , then  is /// returned, not the derived type. ///  public static Type GetDeclaredType( this T obj ) { return typeof( T ); } } } 

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

 string myString = "abc"; object myObj = myString; Type myObjType = myObj.GetDeclaredType(); string myNullString = null; object myNullObj = myNullString; Type myNullObjType = myNullObj.GetDeclaredType(); 

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

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

 return (obj != null) ? obj.GetType() : typeof( T ); 

目前,您无法知道传递给方法的内容。 您可以将其转换为通用方法。 像这样:

public void GetParameterValue(out T destination) { ... }

目标变量的类型始终为System.Object 。 你可以回来

 Convert.ChangeType(paramVal, System.Object). 

@ Rally25s:

 string val; GetParameterValue("parameterName", out val); 

你的消息(在答案中)不清楚那个问题是什么。 如果声明为:

 void GetParameterValue(string parameterName, out T val) { } 

正如您在上面所写的那样,呼叫将起作用(您不需要指定类型)。 我猜这对你不起作用,因为你不能将属性用作“out”参数。 解决这个问题的方法是使用两种方法:

 T GetParameterValue(string parameterName, T ununsed) { } 

这将被称为这样:

 MyObj.SomeProp = GetParameterValue("parameterName", MyObj.SomeProp); 

这是相当的kludgey,但不是更糟糕的方法。


我在C ++中使用但在C#中尚未尝试过的另一种方法是让GetParameterValue()成为您自己设计的一些对象,然后为它实现一些隐式的转换运算符。

 class ParameterHelper { private object value; public ParameterHelper(object value) { this.value = value; } public static implicit operator int(ParameterHelper v) { return (int) v.value; } } ParameterHelper GetParameterValue( string parameterName); MyObj.SomeProp = GetParameterValue("parameterName"); 

当值为null时,我认为不可能获得类型。 此外,由于您在GetParameterValue内部调用,所以您可以做的最好(当值为null时)是获取“目标”参数的类型,即“对象”。 您可以考虑将Type作为参数传递给GetParameterValue,其中包含更多信息,例如:

 public void GetParameterValue(Type sourceType, out object destination) { //... } 

如果没有实例,则没有实例类型。

您可以做的最好是使用引用的类型,这意味着如果您有一个对象引用(如问题中的方法),引用类型是对象。


您可能不应该尝试将一种类型的null实例转换为另一种类型的null实例…

在您的示例中,它将为System.Object类型的null。

你的例子甚至可以编译吗? 我得到一个“无法从’输出字符串’转换为’输出对象’”错误。

在理论层面上,null与C中的void指针实际上不一样,也就是说它拥有一个内存地址,就是这样吗? 如果是这样,则类似于数学中除以零的情况,其结果是未定义的。

可以为此行执行以下操作:

 string val = GetParameterValue("parameterName"); 

只需删除第一个字符串,现在没有重复:

 var val = GetParameterValue("parameterName"); 

不一定是你在找什么,虽然有一个问题是如何解释null?

 //**The working answer** //**based on your discussion eheheheheeh** public void s(out T varName) { if (typeof (T) == typeof(HtmlTable)) { ////////// } } protected void Page_Load(object sender, EventArgs e) { HtmlTable obj=null ; s(out obj); } 

http://msdn.microsoft.com/en-us/library/58918ffs.aspx

要么

 private Hashtable propertyTable = new Hashtable(); public void LoadPropertyTypes() { Type t = this.GetType(); System.Reflection.MemberInfo[] memberInfo = t.GetMembers(); foreach (System.Reflection.MemberInfo mInfo in memberInfo) { string[] prop = mInfo.ToString().Split(Convert.ToChar(" ")); propertyTable.Add(prop[1], prop[0]); } } public string GetMemberType(string propName) { if (propertyTable.ContainsKey(propName)) { return Convert.ToString(propertyTable[propName]); } else{ return "N/A"; } } 

通过这种方式,我们可以使用switch来管理不同的属性类型。