我有一个带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()
目的地为空,因此我们无法在其上调用.GetType()
。我们也不能打电话:
typeof(destination)
因为destination是变量名而不是类型名。
那么有没有办法获得设置为null的对象的类型?我认为必须有一种方法可以知道存储位置的类型,而不会分配任何东西。
为了提供更多信息,我试图创建一个实用程序方法来获取Oracle存储过程的输出参数。问题是DbParameter.Value
是object类型。
对于开发人员来说,理想的做法是:
string val = GetParameterValue("parameterName");
值得注意的是,没有类型的铸造。在实践中,你不知道“等于”的lparam,所以我选择了:
string val;
GetParameterValue("parameterName", out val);
在方法中,我会知道输出变量的目标类型。我猜这是一个不好的假设。作为替代方案,我也写了这个方法:
public T GetParameterValue<T>(string paramName)
所以开发人员可以这样做:
string val = GetParameterValue<string>("parameterName");
我发现显式“字符串”声明是重复的,特别是因为在实践中,目标可能是对象属性和oracle数据类型可能会改变(想想ORM):
MyObj.SomeProp = GetParameterValue<MyObj.SomeProp.GetType()>("parameterName");
但是,如果MyObj.SomeProp为null,则.GetType()
调用失败。 VM必须知道MyObj.SomeProp
的类型,即使它为null,对吗?或者它会如何捕获强制转换异常?
要部分解决我自己的问题,我可以这样做:
MyObj.SomeProp = GetParameterValue<typeof(MyObj).GetField("SomeProp").GetType()>("parameterName");
整个想法是不必在多个位置显式使用Type,因此如果数据类型发生更改,则只需在目标对象(MyObj.SomeProp
)和数据库中进行更改。必须有一个更好的方法...
答案 0 :(得分:32)
那么有没有办法获得设置为null的对象的类型?我认为必须有一种方法可以知道存储位置的类型,而不会分配任何东西。
不一定。你能说的最好的是object
。 null
引用不指向任何存储位置,因此没有元数据可以从中进行确定。
您可以做的最好的事情是将其更改为更通用,例如:
public void GetParameterValue<T>(out T destination)
{
object paramVal = "Blah";
destination = default(T);
destination = Convert.ChangeType(paramVal, typeof(T));
}
可以推断出T
的类型,因此您不需要明确地为方法提供类型参数。
答案 1 :(得分:8)
如果您不介意将方法声明为通用方法,则可能会这样做。试试这个。
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);
}
}
答案 2 :(得分: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 );
}
}
}
由于这是一个扩展方法,因此其参数可以是空引用,并且以下所有方法都可以正常工作:
string myString = "abc";
object myObj = myString;
Type myObjType = myObj.GetDeclaredType();
string myNullString = null;
object myNullObj = myNullString;
Type myNullObjType = myNullObj.GetDeclaredType();
请注意,myObjType
和myNullObjType
都将设置为System.Object,而不是System.String。
如果您确实想要obj的内容类型而不是null,那么将return
行更改为:
return (obj != null) ? obj.GetType() : typeof( T );
答案 3 :(得分:3)
目前您无法知道传递给方法的内容。您可以将其转换为通用方法。像这样:
public void GetParameterValue<T>(out T destination)
{
...
}
答案 4 :(得分:2)
目标变量的类型始终为System.Object
。你可以回来
Convert.ChangeType(paramVal, System.Object).
答案 5 :(得分:1)
@ Rally25s:
string val;
GetParameterValue("parameterName", out val);
目前还不清楚你的消息(在答案中)是什么问题。如果声明为:
void GetParameterValue<T>(string parameterName, out T val) { }
正如您在上面所写的那样,呼叫将起作用(您不需要指定类型)。我猜这对你不起作用,因为你不能将属性用作“out”参数。解决这个问题的方法是使用两种方法:
T GetParameterValue<T>(string parameterName, T ununsed) { }
这将被称为:
MyObj.SomeProp = GetParameterValue("parameterName", MyObj.SomeProp);
这是相当笨拙的,但不是更差的方法。
我在C ++中使用但在C#中尚未尝试过的另一种方法是让GetParameterValue()成为你自己设计的一些对象,然后为它实现一些隐式的转换操作符。 / p>
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");
答案 6 :(得分:0)
在您的示例中,它将为System.Object
类型的null。
你的例子甚至可以编译吗?我得到一个“无法从'输出字符串'转换为'输出对象'”错误。
答案 7 :(得分:0)
我不认为当值为null时可以获取类型。此外,由于您在GetParameterValue内部进行调用,因此您可以做的最好(当值为null时)是获取“目标”参数的类型,即“对象”。您可能考虑将Type作为参数传递给GetParameterValue,您可以在其中获取更多信息,例如:
public void GetParameterValue(Type sourceType, out object destination) { //... }
答案 8 :(得分:0)
如果没有实例,则没有实例类型。
您可以做的最好的事情是使用引用的类型,这意味着如果您有一个对象引用(如问题中的方法),引用类型就是对象。
您可能不应该尝试将一种类型的null实例转换为另一种类型的null实例...
答案 9 :(得分:0)
在理论级别上,null与C中的void指针实际上不一样,也就是说它保存了一个内存地址,就是这样吗?如果是这样,那么它类似于数学中除零的情况,其结果是未定义的。
可以为此行执行以下操作:
string val = GetParameterValue<string>("parameterName");
删除第一个字符串,现在没有重复:
var val = GetParameterValue<string>("parameterName");
不一定是你在寻找什么,虽然有一个问题是如何解释null?
答案 10 :(得分:0)
//**The working answer**
//**based on your discussion eheheheheeh**
public void s<T>(out T varName)
{
if (typeof (T) == typeof(HtmlTable))
{
//////////
}
}
protected void Page_Load(object sender, EventArgs e)
{
HtmlTable obj=null ;
s(out obj);
}
答案 11 :(得分:-1)
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来管理不同的属性类型。