In C# I sometimes have to do something if the object is of some type.
e.g.,
if (x is A)
{
// do stuff but have to cast using (x as A)
}
What would be really nice if inside the if block, we could just use x as if it were an A, since it can't be anything else!
e.g.,
if (x is A)
{
(x as A).foo(); // redundant and verbose
x.foo(); // A contains a method called foo
}
Is the compiler just not smart enough to know this or is there any possible tricks to get similar behavior
Can the Dlang effectively do something similar?
BTW, I'm not looking for dynamic. Just trying to write less verbose code. Obviously I can do var y = x as A; and use y instead of X.
In D, the pattern you'd usually do is:
if(auto a = cast(A) your_obj) {
// use a in here, it is now of type A
// and will correctly check the class type
}
For one statement (or chain-able calls) you can use (x as A)?.Foo() in C# 6.0+ as shown in Is there an "opposite" to the null coalescing operator? (…in any language?).
There is no multiple statements version in the C# language, so if you want you'll need to write your own. I.e. using Action for body of the if statement:
void IfIsType<T>(object x, Action<T> action)
{
if (x is T)
action((T)x);
}
object s = "aaa";
IfIsType<string>(s, x => Console.WriteLine(x.IndexOf("a")));
I believe this is a feature is under consideration for C# 7. See the Roslyn issue for documentation, specifically 5.1 Type Pattern:
The type pattern is useful for performing runtime type tests of reference types, and replaces the idiom
var v = expr as Type;
if (v != null) { // code using v }
With the slightly more concise
if (expr is Type v) { // code using v }`
As for Dlang, I would reference their if statement syntax documentation here.
Related
I stumbled upon this code on github:
if (requestHeaders is {})
and I don't understand what it does exactly.
Upon experimenting it's seems to only be false when requestHeaders is null.
Is this just another way of writing if (requestHeaders != null) or if (!(requestHeaders is null))?
The pattern-matching in C# supports property pattern matching.
e.g.
if (requestHeaders is HttpRequestHeader {X is 3, Y is var y})
The semantics of a property pattern is that it first tests if the input is non-null. so it allows you to write:
if (requestHeaders is {}) // will check if object is not null
You can write the same type checking in any of the following manner that will provide a Not Null Check included:
if (s is object o) ... // o is of type object
if (s is string x) ... // x is of type string
if (s is {} x) ... // x is of type string
if (s is {}) ...
Read more here.
As an addition to #vendettamit's answer:
Since C# 9, it is the same as writing
if (requestHeaders is not null)
which does not require any further explanation
I'm not sure of the terminology for this kind of code, but I want to know if it's possible to instantiate variables after the parentheses, but whilst using reflection.
I have a map which gets loaded from an XML file. This is a collection of (int X, int Y, string S) where the X,Y is the position of some terrain, and S is a string representing the type of the terrain. I have a dictionary to pass between the strings and the relevant types; for example one key-value pair might be "Tree", typeof(Tree).
When using reflection, although I know it's possible to instantiate with parameters, the only way I'm comfortable is just by using Activator.CreateInstance(Type t), i.e. with an empty constructor.
When I had the maps hard coded, I would originally instantiate like this (within some i,j for loop):
case: "Tree"
world.Add( new Tree(i,j) );
Whilst starting to think about reflection and my save file, I changed this to:
world.Add( new Tree() { X = i, Y = j }
However, I realised that this won't work with reflection, so I am having to do the following (Tree inherits from Terrain, and the dictionary just converts the XML save data string to a type):
Type type = dictionary[dataItem.typeAsString];
Terrain t = (Terrain)Activator.CreateInstance(type);
t.X = i;
t.Y = j;
world.Add(t);
I would prefer to do this using something like
Type type = dictionary[dataItem.typeAsString];
world.Add((Terrain)Activator.CreateInstance(type) { X = i, Y = j }
Is there any shortcut like this? I guess if not I could edit world.Add to take an X and Y and cast to Terrain in there to access those variables, but I am still curious as to a) what this {var1 = X, var2 = Y} programming is called, and b) whether something similar exists when using reflection.
This syntax is called Object Initializer syntax and is just syntactic sugar for setting the properties.
The code var result = new MyType { X = x } will be compiled to this:
MyType __tmp = new MyType();
__tmp.X = x;
MyType result = __tmp;
You will have to do that yourself using PropertyInfo.SetValue if you know the instantiated type only at runtime or use the normal property setters if the type is known at compile time.
The answer is no, because the object initialization syntax you mention (introduced with LINQ in 3.0) is an illusion of the compiler. As in, when you type this
var foo = new Foo { Bar = "baz" };
the compiler actually converts it into CLS-compliant IL which equates to
var foo = new Foo();
foo.Bar = "baz";
Phil Haack has a great blog post which not only covers the details of this rewriting done by the compiler, but also some side effects it can cause when dealing with types that implement IDisposable
As all of this is nothing but a feint by the compiler, there is no equivalent using reflection (i.e., Activator.CreateInstance(Type t)). Others will give you workarounds, but in the end there really is no direct equivalent.
Probably the closest generic hack you could manage would be to create a method that accepted an object, then used reflection in order to identify the properties of that object and their respective values in order to perform object initialization for you. It might be used something like this
var foo = Supercollider.Initialize<Foo>(new { Bar = "baz" });
and the code would be something like (this is off the top of my head)
public sealed class Supercollider
{
public static T Initialize<T>(object propertySource)
{
// you can provide overloads for types that don't have a default ctor
var result = Activator.CreateInstance(typeof(T));
foreach(var prop in ReflectionHelper.GetProperties(typeof(T)))
ReflectionHelper.SetPropertyValue(
result, // the target
prop, // the PropertyInfo
propertySource); // where we get the value
}
}
You'd have to get each property from the anonymous object, find a property in your target type with the same exact name and type, then get the value from that property in the anonymous object and set the value of your target's property to this value. Its not incredibly hard, but its absolutely prone to runtime exceptions and issues where the compiler chooses a different type for the anonymous type's property, requiring you be more specific (e.g., new { Bar = (string)null }), which screws with the elegance of the thing.
(T)Activator.CreateInstance(typeof(T), param1, param2, ...);
As described HERE.
public sealed class ReflectionUtils
{
public static T ObjectInitializer<T>(Action<T> initialize)
{
var result = Activator.CreateInstance<T>();
initialize(result);
return result;
}
}
public class MyModel
{
public string Name{get;set;}
}
And after that just make the call :
var myModel = ReflectionUtils.ObjectInitializer<MyModel>(m =>
{
m.Name = "Asdf"
});
The advantage is that in this way you will have type safety and use reflection as minimum required, because we all know that reflection is an expensive operation that should be avoided as much as possible.
You could create a constructor which takes those arguments, then use
Activator.CreateInstance(type, i, j)
But you won't be able to use the object initialization syntax. Which is just sugar candy for setting the properties.
It seems the compiler is not going let this syntax fly.
void main()
{
foo(false?0:"");
}
void foo(int i) {return;}
void foo(string s) {return;}
The only other way I can see of fixing this is something as follows:
void bar(object o)
{
if (o is string){//do this}
else{//im an int, do this}
}
Anyone have any better ideas?
You cannot use a method with a void return type in a ternary expression in this way. End of story.
To understand why this is, remember what the ternary operator actually does -- it evaluates to the following:
(condition ? [true value] : [false value])
What this implies is that the following code:
int x = a ? b : c;
Must be rewritable to:
int x;
if (a)
{
x = b;
}
else
{
x = c;
}
The two above are logically identical.
So how would this work with a method with void as its return type?
// Does this make sense?
int x = condition ? foo(s) : foo(i);
// Or this?
if (condition)
{
x = foo(s);
}
else
{
x = foo(i);
}
Clearly, the above is not legal.
That said, others' suggestions would otherwise be valid if only your foo overloads returned a value.
In other words, if your signatures looked like this:
object foo(string s);
object foo(int i);
Then you could do this (you're throwing away the return value, but at least it'll compile):
object o = condition ? foo(0) : foo("");
Anyway, the ol' if/else is your best bet, in this case.
The method call of foo is determined at compile time, so it cannot call a different method (or overload) based on the result of evaluating the condition. Instead, try something like this:
condition ? foo(0) : foo("")
This way, the compiler will succeed in performing overload resolution and will resolve the first call to foo(int) and the second call to foo(string).
EDIT: As noted by other, you cannot use the ?: operator as a statement, nor can you use methods which return void in it. If your actual methods return compatible types, you could do something like:
int result = condition ? foo(0) : foo("");
If not, you must use an if:
if (condition)
foo(0);
else
foo("");
You're example doesn't make a whole lot of sense (the second example doesn't relate to the first).
I think the first example would be fine as:
void main()
{
foo("");
}
Since 0 will never be passed anyway (false is always false) and you can't use the inline conditional operator without an assignment somewhere (which your example is lacking).
As for the second way, that is probably how I would prefer to see it:
void bar(object o)
{
if(o is string) foo(o as string);
else foo((int)o);
}
I wouldn't pass in an object as a parameter. The int will be boxed, which is a little less efficient. Let the compiler figure out which method to call.
If you wrote:
foo(0);
foo("");
The appropriate method would be called. You could also write:
if (condition) {
foo(0);
} else {
foo("");
}
Depending on what you're trying to do (your example is lacking in a little detail).
If you use Inline if expressions in C#, both parts before and after the ":" have to be of the same type. What you are intending would never work.
Even if you like to do something like this:
DateTime? theTime = true ? DateTime.Now : null;
The compiler is not satisfied. In this case you will have to use:
DateTime? theTime = true ? DateTime.Now : default(DateTime?);
The conditional operator needs the true and false part to be of the same type. Which is why it's not compiling.
var x = condition ? 0 : "";
What type should the compiler choose for x? If you really want it to choose object make a cast or you could force it to choose dynamic in which case method overload would still work but you loose type safety. Both are however strong smells.
Having to test the runtime type is usually a design error but with the limited code (that will always have the same result) it's hard to help with a different approach that would require testing on runtime types
This:
foo(false?0:"")
Could be this:
false ? foo(0) : foo("")
Both results of the conditional operator must of the same type (or be implicitly convertible). So foo(false ? 0 : "") won't work because it is trying to return an Int32 and a String. Here's more information on the conditional operator.
The fix I would do is change that line to false ? foo(0) : foo("").
EDIT: Derp, can't use a conditional operator just in the open like that. They can only be used for assignments. You'll have to use a if/else block. Not in one line, but it'll do in a pinch.
From the docs:
The as operator is like a cast except that it yields null on conversion failure instead of raising an exception. More formally, an expression of the form:
expression as type
is equivalent to:
expression is type ? (type)expression : (type) null
except that expression is evaluated only once.
So why wouldn't you choose to either do it one way or the other. Why have two systems of casting?
They aren't two system of casting. The two have similar actions but very different meanings. An "as" means "I think this object might actually be of this other type; give me null if it isn't." A cast means one of two things:
I know for sure that this object actually is of this other type. Make it so, and if I'm wrong, crash the program.
I know for sure that this object is not of this other type, but that there is a well-known way of converting the value of the current type to the desired type. (For example, casting int to short.) Make it so, and if the conversion doesn't actually work, crash the program.
See my article on the subject for more details.
https://ericlippert.com/2009/10/08/whats-the-difference-between-as-and-cast-operators/
Efficiency and Performance
Part of performing a cast is some integrated type-checking; so prefixing the actual cast with an explicit type-check is redundant (the type-check occurs twice). Using the as keyword ensures only one type-check will be performed. You might think "but it has to do a null check instead of a second type-check", but null-checking is very efficient and performant compared to type-checking.
if (x is SomeType )
{
SomeType y = (SomeType )x;
// Do something
}
makes 2x checks, whereas
SomeType y = x as SomeType;
if (y != null)
{
// Do something
}
makes 1x -- the null check is very cheap compared to a type-check.
Because sometimes you want things to fail if you can't cast like you expect, and other times you don't care and just want to discard a given object if it can't cast.
It's basically a faster version of a regular cast wrapped in a try block; but As is far more readable and also saves typing.
It allows fast checks without try/cast overhead, which may be needed in some cases to handle message based inheritance trees.
I use it quite a lot (get in a message, react to specific subtypes). Try/cast wouuld be significantly slower (many try/catch frames on every message going through) - and we talk of handling 200.000 messages per second here.
Let me give you real world scenarios of where you would use both.
public class Foo
{
private int m_Member;
public override bool Equals(object obj)
{
// We use 'as' because we are not certain of the type.
var that = obj as Foo;
if (that != null)
{
return this.m_Member == that.m_Member;
}
return false;
}
}
And...
public class Program
{
public static void Main()
{
var form = new Form();
form.Load += Form_Load;
Application.Run(form);
}
private static void Form_Load(object sender, EventArgs args)
{
// We use an explicit cast here because we are certain of the type
// and we want an exception to be thrown if someone attempts to use
// this method in context where sender is not a Form.
var form = (Form)sender;
}
}
I generally choose one or the other based on the semantics of the code.
For example, if you have an object that you know that it must be an string then use (string) because this expresses that the person writing the code is sure that the object is a string and if it's not than we already have bigger problems than the runtime cast exception that will be thrown.
Use as if you are not sure that the object is of a specific type but want to have logic for when it is. You could use the is operator followed by a cast, but the as operator is more efficient.
Maybe examples will help:
// Regular casting
Class1 x = new Class1();
Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2
// Casting with as
Class2 y = x as Class2; // Sets y to null if it can't be casted. Does not work with int to short, for example.
if (y != null)
{
// We can use y
}
// Casting but checking before.
// Only works when boxing/unboxing or casting to base classes/interfaces
if (x is Class2)
{
y = (Class2)x; // Won't fail since we already checked it
// Use y
}
// Casting with try/catch
// Works with int to short, for example. Same as "as"
try
{
y = (Class2)x;
// Use y
}
catch (InvalidCastException ex)
{
// Failed cast
}
I've been thinking that it would be useful to be able to do such a thing, for example, to check the parameters for null references and eventually throw an exception.
This would save some typing and also would make it impossible to forget to add a check if a new parameter is added.
Well, not unless you count:
public void Foo(string x, object y, Stream z, int a)
{
CheckNotNull(x, y, z);
...
}
public static void CheckNotNull(params object[] values)
{
foreach (object x in values)
{
if (x == null)
{
throw new ArgumentNullException();
}
}
}
To avoid the array creation hit, you could have a number of overloads for different numbers of arguments:
public static void CheckNotNull(object x, object y)
{
if (x == null || y == null)
{
throw new ArgumentNullException();
}
}
// etc
An alternative would be to use attributes to declare that parameters shouldn't be null, and get PostSharp to generate the appropriate checks:
public void Foo([NotNull] string x, [NotNull] object y,
[NotNull] Stream z, int a)
{
// PostSharp would inject the code here.
}
Admittedly I'd probably want PostSharp to convert it into Code Contracts calls, but I don't know how well the two play together. Maybe one day we'll be able to write the Spec#-like:
public void Foo(string! x, object! y, Stream! z, int a)
{
// Compiler would generate Code Contracts calls here
}
... but not in the near future :)
You can define method parameter with a params keyword. This will make it possible to pass a variable-length number of parameters to your method. You can then iterate over them and check for null references or whatever you want with it.
public void MyMethod(params object[] parameters) {
foreach (var p in parameters) {
...
}
}
// method call:
this.MyMethod("foo", "bar", 123, null, new MyClass());
In my opinion however, it's not a good way of doing things. You will have to manually control the type of your parameters, their position in the input array and you won't be able to use intellisense for them in Visual Studio.
I had the same question some time ago, but wanted to do so for logging purposes. I never found a good solution, but found this link regarding using an AOP based approach for logging method entries and exit. The gist of it is need to use a framework that can read your class and inject code at runtime to do what you you're trying to do. Doesn't sound easy.
How do I intercept a method call in C#?
It is possible to iterate over the parameters that have been declared for a method (via reflection), but I see no way to retrieve the value of those parameters for a specific method call ...
Perhaps you could use Postsharp, and create an aspect in where you perform this check. Then, at compile time, Postsharp can 'weave' the aspect (inject additional code) at every method that you 've written ...
You can look into The Validation Application Block which can be treated as an example of automated validation and The Unity Application Block (in particular its interception feature) in respect to intercepting calls and inspecting parameters.
You could quite probably automate parameter checking with an AOP library such as PostSharp.
After providing a trivial example of a method using the params keyword, RaYell says:
In my opinion however, it's not a good
way of doing things. You will have to
manually control the type of your
parameters, their position in the
input array and you won't be able to
use intellisense for them in Visual
Studio.
I would certainly agree that declaring a method that takes two strings, one int, an object that can be null, and another MyClass object using params is a bad idea. However, there are (in my opinion) perfectly valid and appropriate applications of the params keyword, namely when the parameters are all of the same type. For example:
public T Max<T>(T x, T y) where T : IComparable<T> {
return x.CompareTo(y) > 0 ? x : y;
}
public T Max<T>(params T[] values) where T : IComparable<T> {
T maxValue = values[0];
for (int i = 1; i < values.Length; i++) {
maxValue = Max<T>(maxValue, values[i]);
}
return maxValue;
}
var mandatoryFields = (new object[] { input1, input2 }).Where(v => v == null || v.ToString().Trim() == "");
You will get the list of null parameters.
So then you can just add
if(mandatoryFields.ToArray().Count > 0){}