Extend "object" with a null check more readable than ReferenceEquals - c#

I tried to extend "object" to allow a more readable check if an object is null.
Now, object.ReferenceEquals really checks for a null object, (the rare times it will not apply are since the operator == can be overridden. the object.Equals(null) method can also be overridden).
But the object.ReferenceEquals(null, obj); is not too readable is it?... So, I thought, why not write an extension method to the System.object that will provide that check using object.IsNull(obj);
I've tried:
public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj;
// Why does this line fail? the extension method is not recognized
// I get: 'object' does not contain a definition for "IsNull"
bool itIsANull = object.IsNull(obj);
}
}
What did I miss?

Extension methods can be invoked only on instance and not on a class that they extend. So this line of code bool itIsANull = object.IsNull(obj); is incorrect because object is type and not an instance. Change it to :
bool itIsANull = (new object()).IsNull();
Or you can call it on class MyExtClass but not on object class (which is located in mscore.lib) :
MyExtClass.IsNull(new object());
P.S.
It looks like you missed something about extension methods. The truth is that they have nothing to do with classes that they extend. It's just a convenience that is provided for us by Intellisense with use of reflection.
Object class is located in mscorelib and is immutable. You can't add something to it. But what really happens is that Intellisense searches for all public methods that are located in public static classes and accept first argument with keyword 'this' as parameter. If one is found it's 'mapped' to the class that it extends. So when we type obj.MyExtMethod() on instance of that class it is automatically converted by compiler to Helper.MyExtMethod(obj); (if helper is our static class);

Try
bool itIsANull = obj.IsNull();

You wrote an extension method, and extension methods exist in a different type but extend objects of the specified type by another method.
But when you call object.IsNull(), then you are looking for a static method that exists on the object type.
Instead, you have two ways to call your method:
// either the static method on the class
MyExtClass.IsNull(obj);
// or using the actual feature of extension methods
obj.isNull();
Because it’s an extension method, the latter form will be automatically converted into the former at compile time.

You are calling the extension method on the object itself. You should call the methd on the instance instead -
bool itIsANull = obj.IsNull()

Try:
class Program
{
static void Main(string[] args)
{
var o = new object();
if (o.IsNull())
{
Console.Write("null");
}
}
}
public static class Request
{
public static bool IsNull(this object obj)
{
return ReferenceEquals(obj, null);
}
}

public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public class SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj =null;
bool itIsANull = obj.IsNull();
}
}

Related

Why does HasFlag extension method on Enum trump Enum.HasFlag?

If I create an extension method on Enum called HasFlag, whenever I try to call HasFlag on an enum instance, it uses the extension method, rather than the instance method. Why?
public static class Extensions
{
public static bool HasFlag(this Enum e)
{
return false
}
}
With code:
public enum Foo
{
A, B, C
}
public void Whatever()
{
Foo e = Foo.A;
if (e.HasFlag())
{
// ...
}
}
Compiles to:
public void Whatever()
{
Foo e = Foo.A;
if (Extensions.HasFlag(e))
{
// ...
}
}
Why doesn't the compiler use the Enum.HasFlag instance method?
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
Extension methods cannot be override on instance main methods and it will not know which method to call:
The call is ambiguous between the following methods
The only way around this is to call your extension method using normal static method syntax. So instead of this:
e.HasFlag();
you would have to do this:
Extensions.HasFlag(e);
But if you add other parameters to your extension methods then it is not same to main methods, so when you call HasFlag method, the extension method called actually. For example:
public static bool HasFlag(this Enum e, bool isNullable)
{
return false;
}
References:
Extension Methods (C# Programming Guide)
Extension Methods, Nulls, Namespaces and Precedence in C#

Can't call overriden toSting()

I just start with c#.
I want to override toString() method with parameter. i do:
public string ToString(bool param)
{
if (param)
{
return string.Format(FIO);
}
else
{
return string.Format(Address);
}
}
And call it:
myClass.toString(true);
But get error:
method toString() has 0 parameters but invoked with 1 argument.
Whats can be wrong?
Given this class:
class MyClass
{
public string ToString(bool param)
{
return param.ToString();
}
}
This code will work as expected:
MyClass myClass = new MyClass();
string s = myClass.ToString(true);
Therefore you have an error in part of the code that you are not showing us.
Possibilities:
Typo in the method name?
Using the wrong class?
C# is case sensitive. Your method is "ToString", but you are calling "toString"
change
myClass.toString(true);
to
myClass.ToString(true); // <-- capital T
to override - you need to use the override keyword. However, you cannot override the default ToString() method since it is parameterless so you cannot "modify" it to add a parameter thus you need to create another method.
but your example does not work anyway. C# is case sensitive so you need to call:
myClass.ToString(true)
NOT:
myClass.toString(true)
The Error is telling you exactly what is wrong.
When overriding a method (where you missed the "override") keyword you have to keep the parameters. So you can overwrite .ToString(), but not .ToString(bool something)
As you surely want to achive something completely different than the .ToString()-Method I would simply advice to write a complete own method instead of overwriting
My Suggestion would be:
public override string ToString() {
return string.Format(Address);
}
public string ToStringParam() {
return string.format(FIO);
}
I think you are using the wrong ToString from the base class. For a reason the complier does not find the correct to string; Maybe you are casting somewhere the object.
For this problem; I recommend you to use the Extension Methods:
namespace ExtensionMethods
{
public static class MyExtensions
{
// I DONOT KNOW YOUR OBJECT TYPE I JUST HAVE USED A DUMMY THING; YOU CAN REPLACE IT!!!!
public static string ToString(this MyType myClass, bool param)
{
if (param)
{
return string.Format(myClass.FIO);
}
return string.Format(myClass.Address);
}
}
}

How to Extend the Type Class

this is my code:
bool ch=Type.IsBuiltIn("System.Int32"); // not working-> syntax error
public static class MyExtentions
{
public static bool IsBuiltIn(this Type t, string _type)
{
return (Type.GetType(_type) == null) ? false : true;
}
}
Please I want Extend Type Class by IsBuiltIn new method
You can't have static extension methods. Your extension method works on an instance of the Type class, so to call it you'd have to do something like this:
typeof(Type).IsBuiltIn("System.Int32")
The workaround for this is to just put your extension method in a utility class, e.g. like the following, and call it like a normal static function:
public static class TypeExt
{
public static bool IsBuiltIn(string _type)
{
return Type.GetType(_type) == null;
}
}
// To call it:
TypeExt.IsBuiltIn("System.Int32")
By the way, I don't think this will tell you whether the type is "built-in"; it will merely tell you whether a type with the given name has been loaded into the process.
Extension methods are intended to describe new APIs on instances, not types. In your case, that API would be something like:
Type someType = typeof(string); // for example
bool isBuiltIn = someType.IsBuiltIn("Some.Other.Type");
which... clearly isn't what you wanted; the type here adds nothing and is not related to the IsBuiltIn. There is no compiler trick for adding new static methods to existing types, basically - so you will not be able to use Type.IsBuiltIn("Some.Other.Type").
You can't extend the Type class. You need an instance of the class to create an extension method.
Edit:
See here and here.

Automatic type Conversion in C#

I know that you could override an object's ToString() Method, so that everytime you call an object or pass it to a function that requires a String type it will be converted to a String.
I have written several extension methods for object type 'object'
public static DateTime ToDate(this object date)
{
return DateTime.Parse(date.ToString());
}
public static int ToInteger(this object num)
{
return Int32.Parse(num.ToString());
}
public static long ToLong(this object num)
{
return Int64.Parse(num.ToString());
}
so that I could just call them like this:
eventObject.Cost = row["cost"].ToString();
eventObject.EventId = row["event_id"].ToLong();
However, what I want to accomplish is to convert the row objects which is of type 'object' to its correct type based on the property types on my 'eventObject'. So, I could call it like this:
eventObject.Cost = row["cost"];
eventObject.EventId = row["event_id"];
The row is a DataRow if that matters.
C# supports implicit conversion for types and you can use it for your custom types like the following:
class CustomValue
{
public static implicit operator int(CustomValue v) { return 4; }
public static implicit operator float(CustomValue v) { return 4.6f; }
}
class Program
{
static void Main(string[] args)
{
int x = new CustomValue(); // implicit conversion
float xx = new CustomValue(); // implicit conversion
}
}
And supports extension methods, but doesn't support implicit conversion as an extension method like the following:
static class MyExtension
{
// Not supported
public static implicit operator bool(this CustomValue v)
{
return false;
}
}
I know that you could override an
object's ToString() Method, so that
everytime you call an object or pass
it to a function that requires a
String type it will be converted to a
String.
No, you are wrong. The following code won't compile:
class MyClass
{
public override string ToString()
{
return "MyClass";
}
}
static void MyMethod(string s) { }
static void Main(string[] args)
{
MyMethod(new MyClass()); //compile error
}
The compiler will not get the type of MyMethod parameter(which is string) first and try to convert the argument you passed(whose type is MyClass) to it. I guess you are probably mislead by something like Console.WriteLine. Base on the code above,
Console.WriteLine(new MyClass()) prints "MyClass" to the console, it seems that the compiler knows you should pass a string to Console.WriteLine and try to convert MyClass to string. But the essential is Console.WriteLine has several overloads, one of them is for object:
//from Console.cs
public static void WriteLine(object value)
{
//in this method there is something like
//Console.WriteLine(value.ToString());
}
I believe what you're looking for is implicit conversion, which is described here: http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx.
However, adding these to object would be a very bad idea, for reasons outlined on the page I've linked to.
Forgive me if I'm stating the obvious but I got this impression after reading your question.
You know the basetype of every type in .NET is object right?
So the column in the datarow which you describe of type object could also just as well be of the same type as the member you're trying to assign to and then a simple cast is needed.
for instance
eventObject.EventId = (int)row["event_id"];
To sum up - just define these methods and you can use objects of class Test in methods requiring String as a parameter.
class Test
{
private String txt;
public static implicit operator string(Test t)
{
return t.ToString();
}
public override string ToString()
{
return txt;
}
}

Calling a static method on a generic type parameter

I was hoping to do something like this, but it appears to be illegal in C#:
public Collection MethodThatFetchesSomething<T>()
where T : SomeBaseClass
{
return T.StaticMethodOnSomeBaseClassThatReturnsCollection();
}
I get a compile-time error:
'T' is a 'type parameter', which is not valid in the given context.
Given a generic type parameter, how can I call a static method on the generic class? The static method has to be available, given the constraint.
In this case you should just call the static method on the constrainted type directly. C# (and the CLR) do not support virtual static methods. So:
T.StaticMethodOnSomeBaseClassThatReturnsCollection
...can be no different than:
SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection
Going through the generic type parameter is an unneeded indirection and hence not supported.
To elaborate on a previous answer, I think reflection is closer to what you want here. I could give 1001 reasons why you should or should not do something, I'll just answer your question as asked. I think you should call the GetMethod method on the type of the generic parameter and go from there. For example, for a function:
public void doSomething<T>() where T : someParent
{
List<T> items=(List<T>)typeof(T).GetMethod("fetchAll").Invoke(null,new object[]{});
//do something with items
}
Where T is any class that has the static method fetchAll().
Yes, I'm aware this is horrifically slow and may crash if someParent doesn't force all of its child classes to implement fetchAll but it answers the question as asked.
You can do what I call a surrogate singleton, I've been using it as a sort of "static inheritance" for a while
interface IFoo<T> where T : IFoo<T>, new()
{
ICollection<T> ReturnsCollection();
}
static class Foo<T> where T : IFoo<T>, new()
{
private static readonly T value = new();
public static ICollection<T> ReturnsCollection() => value.ReturnsCollection();
}
// Use case
public ICollection<T> DoSomething<T>() where T : IFoo<T>, new()
{
return Foo<T>.ReturnsCollection();
}
The only way of calling such a method would be via reflection, However, it sounds like it might be possible to wrap that functionality in an interface and use an instance-based IoC / factory / etc pattern.
It sounds like you're trying to use generics to work around the fact that there are no "virtual static methods" in C#.
Unfortunately, that's not gonna work.
I just wanted to throw it out there that sometimes delegates solve these problems, depending on context.
If you need to call the static method as some kind of a factory or initialization method, then you could declare a delegate and pass the static method to the relevant generic factory or whatever it is that needs this "generic class with this static method".
For example:
class Factory<TProduct> where TProduct : new()
{
public delegate void ProductInitializationMethod(TProduct newProduct);
private ProductInitializationMethod m_ProductInitializationMethod;
public Factory(ProductInitializationMethod p_ProductInitializationMethod)
{
m_ProductInitializationMethod = p_ProductInitializationMethod;
}
public TProduct CreateProduct()
{
var prod = new TProduct();
m_ProductInitializationMethod(prod);
return prod;
}
}
class ProductA
{
public static void InitializeProduct(ProductA newProduct)
{
// .. Do something with a new ProductA
}
}
class ProductB
{
public static void InitializeProduct(ProductB newProduct)
{
// .. Do something with a new ProductA
}
}
class GenericAndDelegateTest
{
public static void Main()
{
var factoryA = new Factory<ProductA>(ProductA.InitializeProduct);
var factoryB = new Factory<ProductB>(ProductB.InitializeProduct);
ProductA prodA = factoryA.CreateProduct();
ProductB prodB = factoryB.CreateProduct();
}
}
Unfortunately you can't enforce that the class has the right method, but you can at least compile-time-enforce that the resulting factory method has everything it expects (i.e an initialization method with exactly the right signature). This is better than a run time reflection exception.
This approach also has some benefits, i.e you can reuse init methods, have them be instance methods, etc.
You should be able to do this using reflection, as is described here
Due to link being dead, I found the relevant details in the wayback machine:
Assume you have a class with a static generic method:
class ClassWithGenericStaticMethod
{
public static void PrintName<T>(string prefix) where T : class
{
Console.WriteLine(prefix + " " + typeof(T).FullName);
}
}
How can you invoke this method using relection?
It turns out to be very easy… This is how you Invoke a Static Generic
Method using Reflection:
// Grabbing the type that has the static generic method
Type typeofClassWithGenericStaticMethod = typeof(ClassWithGenericStaticMethod);
// Grabbing the specific static method
MethodInfo methodInfo = typeofClassWithGenericStaticMethod.GetMethod("PrintName", System.Reflection.BindingFlags.Static | BindingFlags.Public);
// Binding the method info to generic arguments
Type[] genericArguments = new Type[] { typeof(Program) };
MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments);
// Simply invoking the method and passing parameters
// The null parameter is the object to call the method from. Since the method is
// static, pass null.
object returnValue = genericMethodInfo.Invoke(null, new object[] { "hello" });
As of now, you can't. You need a way of telling the compiler that T has that method, and presently, there's no way to do that. (Many are pushing Microsoft to expand what can be specified in a generic constraint, so maybe this will be possible in the future).
Here, i post an example that work, it's a workaround
public interface eInterface {
void MethodOnSomeBaseClassThatReturnsCollection();
}
public T:SomeBaseClass, eInterface {
public void MethodOnSomeBaseClassThatReturnsCollection()
{ StaticMethodOnSomeBaseClassThatReturnsCollection() }
}
public Collection MethodThatFetchesSomething<T>() where T : SomeBaseClass, eInterface
{
return ((eInterface)(new T()).StaticMethodOnSomeBaseClassThatReturnsCollection();
}

Categories

Resources