IsAssignableFrom or AS? - c#

I have next code:
private T CreateInstance<T>(object obj) // where T : ISomeInterface, class
{
...
if (!typeof(T).IsAssignableFrom(obj.GetType())) { throw ..; }
return (T)obj;
}
Can it be replaced with this:
T result = obj as T;
if (result == null) { throw ..; }
return result;
If not - why?

What about if (!(bar is T)) { throw ..; }
Alternatively if you don't need your own exception message the simplest answer is just to do:
return (T)obj;
The reason if that if it's not castable an InvalidCastException will be thrown and the return ignored. Unless you're adding some more logic or a custom error message there's no need to do a check and throw your own exception.

Another variant:
private T CreateInstance<T>(object obj) where T : ISomeInterface // as OP mentioned above
{
...
T result = obj as T;
if (result == null)
{ throw ..; }
else
return result;
}

Yes you can use your as operator code there instead of the original code, so long as T is a reference type or nullable.
as is the recommended way of casting in C# (see item 3 of Effective C#, by Bill Wagner)
From system.type.isassignablefrom:
[returns] true if c and the current Type represent the same type, or if the current Type is in the inheritance hierarchy of c, or if the current Type is an interface that c implements, or if c is a generic type parameter and the current Type represents one of the constraints of c. false if none of these conditions are true, or if c is null.
From 7.10.11 of the C# spec:
In an operation of the form E as T, E must be an expression and T must be a reference type, a type parameter known to be a reference type, or a nullable type
So you can see that they do comparable checks.

Maybe this (less brackets, better readability)
if (obj is T)
{
return (T)obj;
}
else
throw new ...
EDITED
by reduced number of brackets I originally meant inverted check: ie
if (obj is T)
instead of
if (!(obj is T))
so final version can be
if (obj is T)
{
return (T)obj;
}
throw new ...
or
if (obj is T)
{
return (T)obj;
}
else
{
throw new ...
}

See this post
The second one is safe...because at the first one if obj is null you will get exception (obj.GetType() --> NullReferenceException).
When you place "is" and then "as" is cause performance issues..

The class constraint where T : class allows you to use the as T statement.
private T CreateInstance<T>(object obj) where T : class
{
if (!(obj is T)) { throw new ArgumentException("..."); }
return obj as T;
}
or
private T CreateInstance<T>(object obj)
{
if (!(obj is T)) { throw new ArgumentException("..."); }
return (T)obj;
}

You're probably looking for the is keyword, with the syntax expression is type
Documentation describes it as performing the checks you want:
An is expression evaluates to true if
both of the following conditions are
met:
• expression is not null.
• expression
can be cast to type. That is, a cast
expression of the form
(type)(expression) will complete
without throwing an exception.
Edit
However, if instead of just working out whether you can cast something before you try, the as keyword is probably your best solution as you describe in your post.
The following code would perform the same function though...
try
{
T result = (T)obj;
return result;
}
catch (InvalidCastException ex)
{
// throw your own exception or deal with it in some other way.
}
Which method you prefer is up to you...

IsAssignableFrom used by this scene:
foreach (PropertyInfo property in GetType().GetProperties())
{
if (typeof(SubPresenter).IsAssignableFrom(property.PropertyType))
{//Do Sth.}
}

Just for the developers who like to play the numbers game (who doesn't!).
Below you'll find a performance comparison test for IsAssignableFrom vs. As. Of course this will only count if you have an instance.
The result of the test (one million attempts):
IsAssignableFrom: 146 ms elapsed
AsOperator: 7 ms elapsed
[TestMethod]
public void IsAssignableFromVsAsPerformanceTest()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int attempts = 1000000;
string value = "This is a test";
for (int attempt = 0; attempt < attempts; attempt++) {
bool isConvertible = typeof(IConvertible).IsAssignableFrom(value.GetType());
}
stopwatch.Stop();
Console.WriteLine("IsAssignableFrom: {0} ms elapsed", stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
for (int attempt = 0; attempt < attempts; attempt++) {
bool isConvertible = value as string != null;
}
stopwatch.Stop();
Console.WriteLine("AsOperator: {0} ms elapsed", stopwatch.ElapsedMilliseconds);
}

It may have been intended to handle cases where a conversion constructor would allow the operation, but apparently IsAssignableFrom doesn't handle that either. Don't see anything that can handle that. So I don't see how to check for cases like this:
class Program
{
static void Main(string[] args)
{
B bValue = new B(123);
Console.WriteLine(typeof(A).IsAssignableFrom(bValue.GetType()));
//Console.WriteLine(bValue is A);
//Console.WriteLine(bValue as A == null);
A aValue = bValue;
Console.WriteLine(aValue.ToString());
}
}
class A
{
string value;
public A(string value)
{
this.value = value;
}
public override string ToString()
{
return value;
}
}
class B
{
int value;
public B(int value)
{
this.value = value;
}
public static implicit operator A(B value)
{
return new A(value.value.ToString());
}
}
In the end, I don't see any reason why you wouldn't want to use your version of the code, unless you want the code to throw an exception when obj is null. That's the only difference I can see. obj.GetType() will throw an null reference exception when obj is null instead of throwing the specified exception.
Edit: I see now your version of the code will not compile if T can be a value type, but the other suggested solution like "if (obj is T) return (T)obj;" will compile. So I see why your suggested alternative will not work, but I don't see why you couldn't use "is".

Or even better because its easer to read true conditionals.
if(obj is T){
//Create instance.
}
else{
throw new InvalidArgumentException("Try Again");
}

Related

When can a null check throw a NullReferenceException

I know this might seem impossible at first and it seemed that way to me at first as well, but recently I have seen exactly this kind of code throw a NullReferenceException, so it is definitely possible.
Unfortunately, there are pretty much no results on Google that explain when code like foo == null can throw a NRE, which can make it difficult to debug and understand why it happened. So in the interest of documenting the possible ways this seemingly bizarre occurrence could happen.
In what ways can this code foo == null throw a NullReferenceException?
in C# you can overload operators to add custom logic on some comparison like this. For example:
class Test
{
public string SomeProp { get; set; }
public static bool operator ==(Test test1, Test test2)
{
return test1.SomeProp == test2.SomeProp;
}
public static bool operator !=(Test test1, Test test2)
{
return !(test1 == test2);
}
}
then this would produce a null reference exception:
Test test1 = null;
bool x = test1 == null;
One example is with getters:
class Program
{
static void Main(string[] args)
{
new Example().Test();
}
}
class Example
{
private object foo
{
get => throw new NullReferenceException();
}
public void Test()
{
Console.WriteLine(foo == null);
}
}
This code will produce a NullReferenceException.
While quite esoteric, it is possible to cause this type of behavior via custom implementations of DynamicMetaObject. This would be a rare but interesting example of where this could occur:
void Main()
{
dynamic foo = new TestDynamicMetaObjectProvider();
object foo2 = 0;
Console.WriteLine(foo == foo2);
}
public class TestDynamicMetaObjectProvider : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new TestMetaObject(parameter, BindingRestrictions.Empty, this);
}
}
public class TestMetaObject : DynamicMetaObject
{
public TestMetaObject(Expression expression, BindingRestrictions restrictions)
: base(expression, restrictions)
{
}
public TestMetaObject(Expression expression, BindingRestrictions restrictions, object value)
: base(expression, restrictions, value)
{
}
public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
{
// note it doesn't have to be an explicit throw. Any improper property
// access could bubble a NullReferenceException depending on the
// custom implementation.
throw new NullReferenceException();
}
}
Not literally your code, but awaiting a null task will also throw:
public class Program
{
public static async Task Main()
{
var s = ReadStringAsync();
if (await s == null)
{
Console.WriteLine("s is null");
}
}
// instead of Task.FromResult<string>(null);
private static Task<string> ReadStringAsync() => null;
}
Do note however that the debugger can get the location of throwing statements wrong. It might show the exception thrown at the equality check, while it occurs at earlier code.
foo == null does indeed to operator overload resolution, and the operator in question didn't handle being passed a null. We are starting to consider writing foo == null obsolete and preferring (taking a page from Visual Basic) foo is null or !(foo is null) which is soon to be full is not null to explicitly inline a null pointer check.
Fix your operator== implemenation. It shouldn't throw, but it is.

In C# can I write a generic function to return null or the value as a string?

Basically I want the following generic function:
public string StringOrNull<T> (T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
I know I could use a constraint such as where T: class, but T can be a primitive type, Nullable<>, or a class. Is there a generic way to do this?
Edit
Turns out I jumped the gun. This actually works just fine as this sample shows:
class Program
{
static void Main(string[] args)
{
int i = 7;
Nullable<int> n_i = 7;
Nullable<int> n_i_asNull = null;
String foo = "foo";
String bar = null;
Console.WriteLine(StringOrNull(i));
Console.WriteLine(StringOrNull(n_i));
Console.WriteLine(StringOrNull(n_i_asNull));
Console.WriteLine(StringOrNull(foo));
Console.WriteLine(StringOrNull(bar));
}
static private string StringOrNull<T>(T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
}
default Keyword in Generic Code
In generic classes and methods, one issue that arises is how to assign a default value to a parameterized type T when you do not know the following in advance:
Whether T will be a reference type or a value type.
If T is a value type, whether it will be a numeric value or a struct.
Here's a fun one:
public static class ExtensionFunctions{
public static string ToStringOrNull( this object target ) {
return target != null ? target.ToString() : null;
}
}
The cool part? This will work:
( (string) null ).ToStringOrNull();
So will this:
5.ToStringOrNull();
Extension functions are pretty awesome... they even work on null objects!
If you pass a primitive type, it will automatically be boxed, so you don't need to worry about the null comparison. Since boxing occurs automatically, you can even explicitly compare an int to null without an error, but the result will always be false (and you'll probably get a compiler warning telling you so).
You can use default keyword to return the default of T:
public string StringOrNull<T> (T value)
{
.....
return default(T).ToString();
}
Why generic?
public string StringOrNull (object value)
{
if (value != null){
return value.ToString();
}
return null;
}

Question about checking for null values

I just got into a debate with one of my coworkers about checking for null values.
He SWEARS that "in certain situations" the code below would give him a null value exception:
string test = null;
if(test == null) //error here
{
}
but that if changed the code to this there would be no error:
string test = null;
if(null == test) //NO error here
{
}
I told him there was no way this could happen but he swears it fixed his code. Is there any possible situation where the above change could fix an error?
Not with string, no. You could do so with a badly written == overload though:
using System;
public class NaughtyType
{
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object other)
{
return true;
}
public static bool operator ==(NaughtyType first, NaughtyType second)
{
return first.Equals(second);
}
public static bool operator !=(NaughtyType first, NaughtyType second)
{
return !first.Equals(second);
}
}
public class Test
{
static void Main()
{
NaughtyType nt = null;
if (nt == null)
{
Console.WriteLine("Hmm...");
}
}
}
Of course, if you changed the equality operator to this:
public static bool operator ==(NaughtyType first, NaughtyType second)
{
return second.Equals(first);
}
then your colleagues code would fail, but yours wouldn't! Basically if you overload operators properly - or use types which don't overload operators - this isn't a problem. If your colleague keeps claiming he's run into it, ask him to reproduce it. He certainly shouldn't be asking you to reduce readability (I believe most people find the first form more readable) on the basis of something he can't demonstrate.
I think this is a left-over from a 'best practice' in C/C++, because using '=' instead of '==' is an easy to make mistake:
if(test = null) // C compiler Warns, but evaluates always to false
if(null = test) // C compiler error, null cannot be assigned to
In C#, they both produce an error.
You're right. If he can reproduce this without an overloaded == operator, invite him to post it here.
The test of if (test == null) if test is a string is valid and will never give an exception. Both tests are also essentially exactly the same.

Generic TryParse Extension method

Code taken from here
I would like to hear some expert opinions on this extension method. I do plan to use it, but would like to hear about any known problems i may face.
Am i better of using on primative types TryParse methods?
public static T? TryParse<T>(this object obj) where T : struct
{
if (obj == null) return null;
T? result = null;
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
try
{
string str = obj.ToString();
result = (T)converter.ConvertFromString(str);
}
catch (Exception ex)
{
throw ex;
}
}
return result;
}
The TryParse pattern is best following the standard pattern, which allows use with non-structs, too:
public static bool TryParse<T>(string s, out T value) {
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try {
value = (T) converter.ConvertFromString(s);
return true;
} catch {
value = default(T);
return false;
}
}
Note I've accepted a string here, because that is what me most commonly mean by TryParse; otherwise, Convert.ChangeType might be more appropriate.
I see no reason for this to be an extension method (as per this in the question's example), and certainly it is inadvisable to pollute object with too many extension methods.
The extensions below might be useful to you. They work on any type that has a Parse or TryParse method...
They come from my Extensions library here:
http://www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx
Although that project is probably a bit out-of-date...I'll have to update it as some point :-D
Hope this helps!
public static class StringExtensions
{
public static TOut ParseOrDefault<TOut>(this string input)
{
return input.ParseOrDefault(default(TOut));
}
public static TOut ParseOrDefault<TOut>(this string input, TOut defaultValue)
{
Type type = typeof(TOut);
MethodInfo parseMethod = type.GetMethod("Parse", new Type[] { typeof(string) });
if (parseMethod != null)
{
var value = parseMethod.Invoke(null, new string[] { input });
return (value is TOut ? (TOut)value : defaultValue);
}
else { return defaultValue; }
}
public static bool TryParseOrDefault<TOut>(this string input, out TOut output)
{
return input.TryParseOrDefault(out output, default(TOut));
}
public static bool TryParseOrDefault<TOut>(this string input, out TOut output, TOut defaultValue)
{
output = defaultValue;
Type type = typeof(TOut);
MethodInfo parseMethod = type.GetMethod(
"TryParse",
new Type[] { typeof(string), typeof(TOut).MakeByRefType() });
if (parseMethod != null)
{
object[] parameters = new object[] { input, output };
var value = parseMethod.Invoke(null, parameters);
if (value is bool)
{
bool successful = (bool)value;
if (successful)
{
output = (TOut)parameters[1];
return true;
}
}
}
return false;
}
}
Generics are most useful when you want to vary the public contract of a method or class, and the internals of the method or class don't really care (or care much) about the type that varies.
Some examples:
List<T> is a collection you can put things in, and internally the class doesn't care (much) about what that type is.
T System.Linq.Enumerable.First<T>(IEnumerable<T> source) returns the first element out of a bunch of elements. This method doesn't need to know internally what type that is in order to get the job done.
By contrast, a parsing method must change its behavior based on the type of the result. In the supplied method, there is Strategy which pushes the behaviors out to other methods, but there is a runtime cost for that choice.
The alternative is to let the caller (who must know the Type or they couldn't call the generic method with it), pick the converter. This choice is able to be made at design time or compile time and so incurs 0 runtime cost.
Side Note: Please don't use the re-throw everything idiom. All it does is reset the call stack and you don't ever want to do that.
catch (Exception ex)
{
throw ex;
}
For simpler code, you can do this:
T value = (T)Convert.ChangeType(value, typeof(T));
Credit to Thomas Levesque at https://stackoverflow.com/a/1465930/24315.
It uses reflection and thus may be slow, if performance is an issue.

Equivalent of the C# keyword 'as' in Java

In Java, is it possible to attempt a cast and get back null if the cast fails?
public static <T> T as(Class<T> t, Object o) {
return t.isInstance(o) ? t.cast(o) : null;
}
Usage:
MyType a = as(MyType.class, new MyType());
// 'a' is not null
MyType b = as(MyType.class, "");
// b is null
You can use the instanceof keyword to determine if you can cast correctly.
return obj instanceof String?(String)obj: null;
Of course it can be genericied and made into the function, but I think question was about what means Java have to accomplish this.
You can, but not with a single function in Java:
public B nullCast(Object a) {
if (a instanceof B) {
return (B) a;
} else {
return null;
}
}
EDIT: Note that you can't make the B class generic (for this example) without adding the target class (this has to do with the fact that a generic type is not available to instanceof):
public <V, T extends V> T cast(V obj, Class<T> cls) {
if (cls.isInstance(obj)) {
return cls.cast(obj);
} else {
return null;
}
}
MyType e = ( MyType ) orNull( object, MyType.class );
// if "object" is not an instanceof MyType, then e will be null.
...
public static Object orNull( Object o , Class type ) {
return type.isIntance( o ) ? o : null;
}
I guess this could somehow done with generics also but I think but probably is not what is needed.
This simple method receives Object and returns Object because the cast is performed in the method client.
AFAIK, this would be (one) of the ways to do that:
SomeClassToCastTo object = null;
try {
SomeClassToCastTo object = SomeClassToCastTo.class.cast(anotherObject);
}
catch (ClassCastException e) {
object = null;
}
Ugly, but it should do what you want...
In Java if a cast fails you will get a ClassCastException. You can catch the exception and set the target object to null.
You can either catch the exception:
Foo f = null;
try {
f = Foo(bar);
}
catch (ClassCastException e) {}
or check the type:
Foo f = null;
if (bar instanceof Foo)
f = (Foo)bar;
The two solutions above are somewhat awkward:
Casting and catching ClassCastException: creating the exception object can be expensive (e.g. computing the stack trace).
The nullCast method described earlier means you need a cast method for each cast you want to perform.
Generics fail you because of "type erasure" ...
You can create a static helper method that is guaranteed to return an instance of your target class or null, and then cast the result without fear of exception:
public static Object nullCast(Object source, Class target) {
if (target.isAssignableFrom(source.getClass())) {
return target.cast(source);
} else {
return null;
}
}
Sample call:
Foo fooInstance = (Foo) nullCast(barInstance, Foo.class);
you can handle this catching ClassCastException

Categories

Resources