How to get the lowercase name of an object, even if zero, in C #

I have a C # method

private static string TypeNameLower(object o) { return o.GetType().Name.ToLower(); } 

to give me a lowercase type name of the input object.

But if the input is a string set to null, or the nullable int value is set to null, this method of course fails.

How to get the type name in this situation?

+63
c #
May 30 '09 at 17:21
source share
11 answers

Jeff is right. It's like asking what cake would be in an empty box without a label.

As an alternative to answering Fortran, you can also do the following:

 string TypeNameLower<T>(T obj) { return typeof(T).Name.ToLower(CultureInfo.InvariantCulture); } string TypeNameLower(object obj) { if (obj != null) { return obj.GetType().Name.ToLower(CultureInfo.InvariantCulture); } else { return null; } } string s = null; TypeNameLower(s); // goes to the generic version 

This way, C # will choose universal at compile time if it knows enough about the type you are passing.

+66
May 30, '09 at 17:24
source share

I thought that I would send my answer, although this question is old, because, in my opinion, the accepted answer is incorrect. This answer was pretty creative, so I'm not going to shoot it down. And for all that I know, it could be what the OP really wanted.

But, as you will see from my examples below, I think that in almost all cases the idea of ​​using the common function described in the accepted answer is either (A) not needed or (B) wrong. I copied the generic function that I am talking about from the accepted answer and pasted it below for reference:

 string TypeNameLower<T>(T obj) { return typeof(T).Name.ToLower(); } 

Now let's look at some ways to use this function:

Examples when a common function is not needed:

 var s = "hello"; var t = TypeNameLower(s); //or foreach(char c in "banana") WriteLine(TypeNameLower(c)); //or foreach(MyCustomStruct x in listOfMyCustomStruct) WriteLine(TypeNameLower(x)); 

In these examples, the function works, i.e. returns the correct values, which are "strings", "char" and "mycustomstruct" respectively. However, in all cases like these (i.e., when the general function really returns the correct type), the compiler knows in advance what a certain type of variable is, and, of course, the programmer (unless they are confused by their variable names). Thus, the function is completely unnecessary, and the programmer can do this too:

 var s = "hello"; var t = "string"; //or foreach(char c in "banana") WriteLine("char"); //or foreach(MyCustomStruct x in listOfMyCustomStruct) WriteLine("mycustomstruct"); 

It may seem naive at first, but think about it for a while ... it may take some time for it to really drown ... Try to find ANY scenario in which using a common function provides accurate information on the Runtime that is not yet known (and therefore can be automatically generated by the compiler or code generation utilities such as T4 templates) at compile time .

Now, the point of the previous set of examples was to demonstrate a minor annoyance with a common function - that it is not needed in every case when it returns the correct result. But more importantly, take a look at the examples below. They show that in any other case, the result of the generic function is actually incorrect if you expect the function to return the name of the true type of the runtime of the object. The function actually only guaranteed to return a type name, which can be assigned a true value, which can be an ancestor class, interface or the object itself.

Examples where a common function does not match

 Stream ms = new MemoryStream(); IEnumerable str = "Hello"; IComparable i = 23; object j = 1; TypeNameLower(ms); //returns "stream" instead of "memorystream" TypeNameLower(str); //returns "ienumerable" instead of "string" TypeNameLower(i); //returns "icomparable" instead of "int32" TypeNameLower(j); //returns "object" instead of "int32" TypeNameLower<object>(true); //returns "object" instead of "bool" 

In all cases, the results are completely wrong, as you can see. Now I admit that the last two lines were a little far-fetched to demonstrate this point (not to mention that TypeNameLower(j) will actually be compiled to use a non-universal version of the function, which is also part of the accepted answer - but you get idea ...)

The problem is that the function actually ignores the type of the transmitted object and uses only information about the generalized parameter (compilation time) to return the value.

A better implementation would be as follows:

 string TypeNameLower<T>(T obj) { Type t; if (obj == null) t = typeof(T); else t = obj.GetType(); return t.Name.ToLower(); } 

Now the function returns the name of the true runtime type whenever the object is not null, and the default is to use the compile time / specific type when the type is null .

It is important to note that this function can be used WITHOUT a universal version! The result will be that the function will never return null . The most common return value will be "object", for example:

  object x = null; string s = null; byte[] b = null; MyClass m = null; TypeNameLower(x); // returns "object" TypeNameLower(s); // returns "string" TypeNameLower(b); // returns "byte[]" TypeNameLower(m); // returns "myclass" 

Note that this is actually a function more consistent with the intended purpose, as requested by the OP. That is, if the OP really wants to know what the object type name is, if it was not null, then returning null will never be a suitable answer, since null is NOT a name of any type and typeof (null) is not defined.

Each variable in C # is omitted from System.Object , so by definition, if the value was not null , then it would be Object , and in many cases this is the most that can be determined with respect to a null reference at runtime.

+36
Dec 14 '12 at 7:15
source share
 // Uses the compiler type inference mechanisms for generics to find out the type // 'self' was declared with in the current scope. static public Type GetDeclaredType<TSelf>(TSelf self) { return typeof(TSelf); } void Main() { // ... Foo bar; bar = null; Type myType = GetDeclaredType(bar); Console.Write(myType.Name); } 

Print

 Foo 

I have posted this on a similar topic as well, I hope this will be useful to you .; -)

+19
Jan 12 '10 at 18:51
source share
 if (o == null) return "null"; else return o.GetType().Name.ToLower(); 

simple solution for a simple task: -p

+15
May 30 '09 at 17:25
source share

As others mention, you cannot. This is actually a well-known problem with languages ​​that allow purely null object references. One way around this is to use the "Null Object" template. The basic idea is that instead of using null for empty links, you assign it an instance of the "do nothing" object. For example:

 public class Circle { public virtual float Radius { get; set; } public Circle(float radius) { Radius = radius; } } public class NullCircle : Circle { public override float Radius { get { return float.NaN; } set { } } public NullCircle() { } } 

Then you can pass an instance of NullCircle instead of null , and you can check its type, as in your code.

+8
May 30 '09 at 17:38
source share

As far as I know, you cannot. Null indicates the absence of a value and does not differ for different types.

+3
May 30 '09 at 17:22
source share

There is no concept that an empty string is different from a null array, other than zero. From within your function, you cannot define a type name.

In particular, an instance of the reference class (inside) includes a “pointer” to information about the type of the object. When the input is null, there is no such pointer, so type information does not exist.

+2
May 30 '09 at 17:25
source share

Just expanding @ Josh Einstein's answer.

Below are two extension methods to get the type of a variable, even if it is currently set to null.

  /// <summary> /// Gets an object type even if it is null. /// </summary> /// <typeparam name="T">The type of the object.</typeparam> /// <param name="that">The object being extended.</param> /// <returns>The objects type.</returns> public static Type GetTheType<T>(this T that) { return typeof(T); } /// <summary> /// Gets an object type even if it is null. /// </summary> /// <param name="that">The object being extended.</param> /// <returns>The objects type.</returns> public static Type GetTheType(this object that) { if (that != null) { return that.GetType(); } return null; } 

In addition, here are two simple unit tests for testing extension methods.

  /// <summary> /// Tests to make sure that the correct type is return. /// </summary> [Test(Description = "Tests to make sure that the correct type is return.")] public void Test_GetTheType() { var value = string.Empty; var theType = value.GetTheType(); Assert.That(theType, Is.SameAs(typeof(string))); } /// <summary> /// Tests to make sure that the correct type is returned even if the value is null. /// </summary> [Test(Description = "Tests to make sure that the correct type is returned even if the value is null.")] public void Test_GetTheType_ReturnsTypeEvenIfValueIsNull() { string value = null; var theType = value.GetTheType(); Assert.That(theType, Is.SameAs(typeof(string))); } 

Edit Sorry, I forgot to mention that I need the same function for the project I'm in now. All loans should still go to @Josh Einstein: D

+2
Jul 08 2018-11-18T00:
source share

It is very difficult that C # does not allow such a definition. And the question is not what kind of cake you would have in an empty box - the object consists of two independent components - the "embodiment" of the object and information about the class that was used to create the object. The fact that this information may not be readily available is an omission on the part of C # developers.

All you can do by defining is a pretty distorting method:

 void Method(object obj) { if(obj is int) { //obj is of the int type } else if(obj is SomeComplexType) { //obj is of the SomeComplexType type } } 

So, you can see that even if the object is null, its type information, however, moves with the object, it is not lost, you simply cannot easily get it. But this, to put it mildly, is inconvenient.

+1
Oct 21 '09 at 12:16
source share

If you have an object on its own (say, as an input parameter to a method with an object of type), without a definition or general type, there is no way to find this type. The reason is simple: you cannot send a message (call any method) to an object to ask about a type .

Some answers may come up with some other workarounds, such as using generic types. In this case, you are not requesting a Null object; you are requesting a type type for your type.

+1
Jan 12
source share

Consider this code:

  public class MyClass1{} public class MyClass2{} public static void Test1() { MyClass1 one = null; MyClass2 two = (MyClass2) (object) one; one = new MyClass1(); //invalid cast exception two = (MyClass2)(object) one; } 

The execution type of a null instance of type object , at least in terms of type safety.

0
May 30 '09 at 17:41
source share



All Articles