How to enable generic type parameter for C # method to accept null argument?

private static Matcher<T> EqualTo<T>(T item) { return new IsEqual<T>(item); } 

How to change the above definition of a method so that the following are valid / valid.

 EqualTo("abc"); EqualTo(4); EqualTo(null); // doesn't compile. EqualTo<string>(null) does 

Trying to port some Java code where null seems to be an acceptable value for the T parameter.


Update
Thanks: for all the answers - especially Imon and Jason. I did not want the method call to worry about type-output. The next overload fixed him.

  private static Matcher<object> EqualTo(object item) { return EqualTo<object>(item); } 

Actually, the above question was part of a bigger mystery. The ultimate goal was as follows.

  this.AssertThat(null, EqualTo(null)); this.AssertThat(null, Not(EqualTo("hi"))); this.AssertThat("hi", Not(EqualTo(null))); 

The same fix applies .. RFC . (Ignoring part of the ugly extension method - this is another problem. I wanted to have these methods in all test records without inheritance.)

 public static void AssertThat<T>(this object testFixture, object actual, Matcher<T> matcher, string message = "") { AssertThat(anyObject, (T)actual, matcher, message); } public static void AssertThat<T, TSuper>(this object testFixture, T actual, Matcher<TSuper> matcher, string message = "") where T : TSuper { ... check and assert 
+6
source share
5 answers

Consider the following method:

 public bool IsNullString<T>(T item) { return typeof(T) == typeof(string) && item == null; } 

Yes, this is a pathetically stupid method, and using generics is pointless here, but you will see the moment in the moment.

Now consider

 bool first = IsNullString<string>(null); bool second = IsNullString<Foo>(null); bool third = IsNullString(null); 

In the first and second compiler, the type T can be clearly distinguished (no output is required). Third, how does the compiler conclude that T ? In particular, it cannot distinguish between T == string and T == Foo , or any other type in this regard. Therefore, the compiler should give you a compile-time error.

If you want to get around this, you need to either throw null

 EqualTo((object)null); 

or explicitly specify the type

 EqualTo<object>(null) 

or determine overload

 private static Matcher<object> EqualTo(object item) { return new IsEqual<object>(item); } 
+9
source

Impossible without explicitly specifying T or throwing. Generics are compilation time constructs, and therefore, if the compiler cannot determine the type at compile time, it will not compile (as you can see).

+2
source

Since you cannot do exactly what you want, how to define the EqualTo(object) overload method? This should allow your required syntax.

+2
source

You can get around this limitation using the following syntax:

 EqualTo("abc"); EqualTo(4); EqualTo(default(object)); //equivalently: EqualTo((object)null); 

default(T) is the value that a field of type T has if it is not specified. For reference types, this is null , for value types it is essentially memory filled with null bytes (... which can mean different things for different types, but usually means some version of zero).

I try to avoid null everywhere in my code for now. It also makes it difficult to type in elsewhere, for example, with a declared var field and a triple operator. For example, myArray==null ? default(int?) : myArray.Length myArray==null ? default(int?) : myArray.Length is fine, but myArray==null ? null : myArray.Length myArray==null ? null : myArray.Length will not compile.

+2
source

Perhaps the implementation of the nonequivalent EqualTo, which takes an object as an argument type, will solve the problem of overwriting these lines of code.

0
source

Source: https://habr.com/ru/post/885610/


All Articles