如何确定一个对象是否可以将 ToString 转换为值或类型名称?

How can I determine if an object can ToString into value or type name?

我正在编写 php 服务和我们的 crm 之间的互操作。我需要做的一件事是确保简单类型转换为 ToString() 以便稍后在 json 转换器中使用。

我什至不确定 'simple types' 的名称是什么,但可以这样定义... "an object that represents a low level variable type, containing a single value, not a class or anything with executable functions etc"

我发现 int、string、bool、double 和令人惊讶的枚举将 ToString() 与相当可预测的结果。

int x = 0;
bool y = true;
double z = 1.59 // money
CustomEnum theEnum = CustomEnum.somevalue;

x.ToString() 结果为“0”

y.ToString() 结果为 "true"

z.ToString() 结果为“1.59”

theEnum.ToString() 结果为 "somevalue"

但是如果我使用这个:

List<int> iList = new List<int>();
iList.Add(1);

MyClass theClass = new MyClass();

iList.ToString() 结果为 "System.Collections.Generic.List`1[System.Int32]" theClass.ToString() 结果为 "STTI.NKI.Interop.MyClass"

我不限于列表。我可以有一个 ExpandoObject,或者 class 等等

我完全理解为什么会发生这种情况,我想知道是否有一种快速方法可以确定未知类型的对象是否将 ToString() 转换为预期值,而不是类型名称。我发现做类似

的事情是一种反模式
switch (theObject.GetType())
 case typeof(int):
 case typeof(bool):
 case typeof(doulble):
etc

我不确定这些术语是什么,因此很难用谷歌搜索我的答案。

选项 1:确保每个对象都将覆盖 ToString()。 选项 2:使用反射获取所有对象属性并连接它们。

也许你可以做类似的事情:

bool ToStringIsTyped<T>(T myObj)
{
    return myObj.ToString().Contains(typeof(T).FullName);
}

它可能并非在所有情况下都有效,但可能会得到扩展

所以您想检查一个类型是否有重写的 ToString 方法?为什么不检查 ToString 返回的值是否等于 ToString 的默认实现返回的值?

here我们知道ToString的默认实现是

return GetType().ToString();

因此,我们可以使用它来检查对象是否已覆盖 ToString 方法:

bool toStringOverridden = someObject.GetType().ToString() !=
    someObject.ToString();

我认为这就是您要查找的内容,在 GetMethod 中,第二个参数是一个空数组,用于监视 .ToString(),只需将 i.GetType().GetMethod("ToString", new Type[] { }).DeclaringType == typeof(object) 转换为函数即可。

class Program
    {
        static void Main(string[] args)
        {
            int i = 55;
            var s = "some string";
            var x = new List<string>();
            Console.WriteLine(i.ToString());
            Console.WriteLine(i.GetType().GetMethod("ToString", new Type[] { }).DeclaringType == typeof(object));
            Console.WriteLine(s.ToString());
            Console.WriteLine(s.GetType().GetMethod("ToString",new Type[]{}).DeclaringType == typeof(object));
            Console.WriteLine(x.ToString());
            Console.WriteLine(x.GetType().GetMethod("ToString",new Type[]{}).DeclaringType == typeof(object));
        }
    }

ToString 方法是一个虚拟方法,默认实现在 Object class 中定义,只是 return 对象类型的名称:

public virtual string ToString()
{
  return this.GetType().ToString();
}
例如,

int 将此方法重写为 return 有意义的表示。

你可以做的是使用反射来检测类型是否覆盖了 ToString 方法,如下所示:

public static bool OverridesToString(Type type)
{
    return type.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object);
}

如果是这样,ToString 方法很有可能会 return 一些有意义的东西。

...way to determine if an object of unknown type will ToString() into an expected value, and not the type name...

ToString()object 上的默认实现,根据 documentation、returns "the fully qualified name of the object's type"。

因此我们可以提出这样的假设,即无论何时覆盖 ToString(),它的输出都将是您在问题中指定的意义上的 "useful"。

要检测调用的函数是否是覆盖,我们可以使用this answer,像这样:

if(typeof(ObjectX).GetMethod("ToString").DeclaringType == typeof(ObjectX))
{
    /* ObjectX has overridden ToString() */
}
else
{
    /* ObjectX has inherited ToString() from its base class(es) */
}