I'm wondering about the behavior of extension methods in C#. Please see the examples below:
static string ExtendedToString( this object oObj )
{
return "Object";
}
static string ExtendedToString( this Array oArray )
{
return "Array";
}
// Example 1: int array - working as expected.
int[] o = new int[] { 1, 2, 3 };
o.ExtendedToString( ); // returns "Array"
// Example 2: array as object - did not expect the result.
object o = new int[] { 1, 2, 3 };
o.ExtendedToString( ); // returns "Object"
Why is (in the last case) the object's extension method called and not the one for int[]?
Overload resolution is performed at compile time. The compiler sees that o is declared as object, so it calls the overload that takes an object. The fact that o actually contains an array at runtime is irrelevant, because the compiler doesn't know it.
That's actually not specific to extension methods, you would get the same result by calling it as a normal static method (ExtensionsClass.ExtendedToString(o))
You declared o as object:
object o = new int[] { 1, 2, 3 };
thats why:
o.ExtendedToString( ); // returns "Object"
but you can
int[] obj = o as int[];
obj.ExtendedToString( ); // returns "Array"
as the resolution is depending on the (static) type
Because of static typing. Extension methods are rewrited by compiler as if you called them by regular syntax. At the compile time, second object o has the type of Object, so object's extension method is called
Thomas Levesque already has a perfect explanation of why your code doesn't work, so I won't repeat that. The work around is testing at runtime with is or as:
static string ExtendedToString( this object oObj )
{
if(oObj is Array)
return "Array";
else
return "Object";
}
Generally type testing in such a way is a bit of an anti-pattern and you should prefer virtual methods where possible. But in this case it's probably still the best solution since you can't change the Array/Object classes.
If there are many classes which need special treatment you could consider a Type -> Func<object,string> Dictionary.
Related
First, I don't have much experience in .Net - especially within the last 7 years.
I'm trying to develop an application and would to incorporate another library (https://github.com/Giorgi/Math-Expression-Evaluator)
That library allows me to evaluate math expressions like Evaluate("a+b", a: 1,b: 1). The method signature is public decimal Evaluate(string expression, object argument = null)
I would like to understand better how .Net translates comma-separated arguments into a single "argument".
I'm not sure how to create that argument dynamically.. for example, iterating through a list of values and creating an object that will match the appropriate argument for that signature.
I'm really just looking for pointers for documentation and more information.. Thanks for anything.
EDIT: Sorry.. purposely left it broad because I wasn't looking for people to do my work for me.. just can't seem to find a starting point to do my own research.
The method is called like
dynamic engine = new ExpressionEvaluator() ;
engine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6)) ;
In the body of Evalute() is this code (which turns that argument into a Dictionary of String, Decimal pairs.
if (argument == null)
{
return new Dictionary<string, decimal>();
}
var argumentType = argument.GetType();
var properties = argumentType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && IsNumeric(p.PropertyType));
var arguments = properties.ToDictionary(property => property.Name,
property => Convert.ToDecimal(property.GetValue(argument, null)));
return arguments;
What I'd like to be able to do is parse a String like "a:1,b:2" and turn it into an object that matches that Evaluate() signature.
That library is using high level magic... Very high level :-)
The trick is that the class is declared as:
public class ExpressionEvaluator : DynamicObject
So it is a class that implements the dynamic magic introduced in .NET 4.0
Now... In the class there are two Evaluate methods:
public decimal Evaluate(string expression, object argument = null)
and
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
The only method normally visible and usable is the first one. It is used like:
engine.Evaluate("a + b + c", new { a = 1, b = 2, c = 3 });
The new { ... } creates an anonymous object, that is then "unpacked" here through the use of reflection to a Dictionary<string, decimal> to be fed to the private Evaluate().
If you try to use the other notation, the one like:
engine.Evaluate("a + b + c", a: 1, b: 2, c: 3 });
then the .NET can't match the method to the public Evaluate() that is present, but the class, being a subclass of DynamicObject, causes the C# compiler to write some "magic" code that launches this method (that is still implemented by the ExpressionEvaluator):
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
That first checks that we want to call Evaluate:
if (nameof(Evaluate) != binder.Name)
and if we are trying to call Evaluate, it unpacks the parameters to a new Dictionary<string, decimal>() and then calls the private Evaluate().
As a sidenote, to use the "dynamic" way of writing Evaluate you have to declare the engine variable like;
dynamic dynamicEngine = new ExpressionEvaluator();
So using the dynamic variable type.
Now... As the library is written you can:
Use an anonymous object, with the problem that anonymous objects must have their "shape" defined at compile time (so at compile time you must know that you will need a a, a b and a c. You can't need a d at runtime if you didn't create a new { a, b, c, d } at compile time). See for example a response I gave three years ago about how to create dynamic anonymous types at runtime. One of the reasons I gave for that block of code was:
there are parts of the .NET framework that heavily use reflection to render objects (for example all the various datagrids). These parts are incompatible with dynamic objects and often don't support object[]. A solution is often to encapsulate the data in a DataTable... or you can use this :-)
Note that in one of the comments to that response there is a link to a modified version of my code used by one of the many implementations of Dynamic.Linq.
Use a non-anonymous object (a new Foo { a = 1, b = 2 c = 3 }). The library doesn't make distinctions between anonymous and non-anonymous objects. So same limitation as before, because at compile time you need a Foo class with the right number of parameters
Use the dynamic notation. Sadly even that is quite static. You can't easily add new parameters, that for the number and name of the "variables" must be defined at compile time.
A possible solution is to modify the source code (it is a single file) and make public this method:
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
then you can easily and dynamically populate the Dictionary<string, decimal> arguments
As a newbie I've read about the dangers of passing parameters with the ref keyword. I guess there's great potential to mess up code when a ref variable is modified in part of a program which then changes what happens elsewhere. Objects end up being very tightly coupled. (I recognize there may be places where ref is worthwhile.) What I don't yet know, and am asking about, are the alternatives.
In one program, for example, I create a generic list at startup, which I manipulate in the program's methods. In one method:
//a user is asked a question
//if the response is yes, the list is modified one way and the method returns true
//if the response is no, the list is modified a different way and the method returns false.
So the method returns a Boolean and I pass the list in as a ref. I have several similar methods, each asking users unique questions and then modifying the list in some way.
It seems like a typical alternative might be to bundle the list and a Boolean field into its own class. Somehow this seems like creating an object for nothing more than convenience, just to hold two pieces of data, with no connection to any real world entity.
So, how would you (pseudo)code a method that returns both a generic list and a Boolean value?
EDIT: Here's some actual code
private static bool AskExptQuestion(ref List<StatTest> testList)
{
Console.Write(Constants.ExptQText); //experimental groups?
string response = Console.ReadLine();
//if response==y, it's experimental
if (response == "y")
{
//so select all experimental
var q1List =
from test in testList
where test.isExperimental == true
select test;
//to copy resulting IEnumerable<List> (q1list) to generic List, must copy/cast IEnumerable to a List<t>
testList = q1List.ToList();
return true;
}
//and if response==n, it's not experimental
else
{
//so select all non-experimental
var q1List =
from test in testList
where test.isExperimental == false
select test;
testList = q1List.ToList();
return false;
}
}
Returning a list (or almost anything else, for that matter) along with its characteristic, such as a Boolean value, is a "poster child" of the ref/out feature. This pattern is used in several places in the standard .NET library:
Dictionary.TryGetValue uses this pattern, returning true or false depending on presence of the key in the dictionary, and setting a out to the return object
Integer.TryParse (and other numeric types) use this pattern, returning true when the parse is successful, and setting the value in a out parameter
The difference between ref and out is that ref gives your method an option to keep the old object/value or to supply a new one, while the out forces you to supply a new one before the method returns.
There is no point to create a new class simply to bundle two unrelated types together.
In addition, it is important to understand that modifications to method parameters can happen even in situations when a parameter is not passed by ref or out. When you pass an object of reference (i.e. class) type that is mutable, any modifications to the object done inside the method are visible in the caller.
The only difference when passing by ref or out is that you are allowed to replace the object itself with a new one, while passing a reference type without ref is restricted to mutating the incoming object itself.
From reading your example and comments, it sounds like you might just want the ability to apply some filters to a collection. Why not have your functions return the filters?
private static Predicate<StatTest> AskExptQuestion()
{
Console.Write(Constants.ExptQText); // experimental groups?
bool response = Console.ReadLine() == "y"; // maybe wrap this up in a function to read a yes/no answer
return t => t.isExperimental == response;
}
You might still need that bool return value, though, which can become an out parameter. It’s not clear what that’s for.
in c# paramaters are passed by value.
object types (classes) are implimented by a pointer to an instance in memory.
where passing an object to a method, the pointer is copied to the argument and he then points to the same instance.
if i have:
void foo(MyClass param)
{
param.x = 7;
}
and somewhere else i do:
MyClass obj = new MyClass();
obj.x = 5;
foo(obj);
then after the call to foo() the x property of obj is 7.
if foo is:
void foo(MyClass param)
{
param = new MyClass();
param = 7;
}
then my original obj will still have x equals to 5. this is because i ran over the instance that param was looking at.
now the "ref" keyword:
void foo(ref MyClass param)
{
param = new MyClass();
param = 7;
}
if i call like this:
MyClass obj = new MyClass();
obj.x = 5;
foo(ref obj);
in this combination my obj will be set to the new instance of MyClass and will have x equals 7. the ref means that the variable in the method is the same as the variable passed, and not just pointing to the same instance to start with.
I have a field that is of type 'object'. When I inspect it within the Watch window of visual studio I see its Object[] and when I drill into the elements I see each element is a string.
But when I try to cast this to a String[] I get this error:
Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]
Any reason why I can't do this cast? What is the best way to convert this object to a string array?
This is a particularly confusing feature of C#. Here's the deal.
Throughout this discussion we assume that the element type of an array is a reference type, not a value type.
C# supports unsafe array covariance. That means that if you have an array of string, you can convert it to an array of object, because a string can be converted to an object:
string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal
If you then try to get an element out of a2, it works:
object o3 = a2[0];
That's legal because a2[0] is really a1[0], which is a string, which is convertible to object.
However, if you attempt to write to the array then you'll get an error at runtime:
a2[0] = new object();
This fails at runtime because a2 is really an array of strings, and you can't put a non-string into an array of strings.
So C# is already horribly broken; it is possible to write a program that compiles and looks normal but suddenly crashes with a type exception at runtime because you tried to put an object into an array of objects that is not actually an array of objects.
The feature you want is even more broken than that, and thank goodness C# does not support it. The feature you want is:
object[] a4 = { "Hello" };
string[] a5 = a4;
That would be unsafe array contravariance. It breaks horribly like this:
a4[0] = new Customer(); // Perfectly legal
string s6 = a5[0];
And now we just copied a Customer into a variable of type string.
You should avoid any kind of array covariance or contravariance; array contravariance is, as you've discovered, not legal, and array covariance is making little time bombs in your program that go off unexpectedly. Make your arrays of the right type to begin with.
string[] newarr = Array.ConvertAll(objects, s => (string)s);
--EDIT--
since you've said I have an object (knowing that it is an object[] actually)
string[] newarr = Array.ConvertAll((object[])objects, s => (string)s);
object[] original = new object[]{"1", "2"};
//some code in between here
object obj = original ;
object[] objArray = (object[])obj;
string[] newArray = new string[objArray.Length];
for(int i = 0; i < newArray; i++)
{
newArray[i] = (string)objArray[i];
}
Other answers here are showing you quicker/shorter ways of doing the conversion. I wrote the whole thing out like this because it shows what's really going on and what needs to happen. You should use one of the simpler methods in your actual production code.
The rule in object oriented programming is -
"Derived class can always be type casted to base class" AND
"A Base class can be casted to derived class only if the current instance that base class hold off is actually derived class"
e.g. (A is base and B is derived)
A a = new B(); // legal;
B b = (B) a ; // legal as "a" is actually B (in first statement)
illegal : >
A a = new A();
B b = (B) a; // not legal as "a" is A only.
Same thing is applied to Object and String classes. Object is base class and string is Derived class.
You can convert the real string[] to object[].
This is a Array covariance
Can find a clear example in link.
You should cast each element in the collection and not the collection itself.
object[] ovalues = new object[] { "alpha", "beta" };
string[] svalues = ovalues.Cast<string>().ToArray();
In C# I am trying to write code where I would be creating a Func delegate which is in itself generic. For example the following (non-Generic) delegate is returning an arbitrary string:
Func<string> getString = () => "Hello!";
I on the other hand want to create a generic which acts similarly to generic methods. For example if I want a generic Func to return default(T) for a type T. I would imagine that I write code as follows:
Func<T><T> getDefaultObject = <T>() => default(T);
Then I would use it as
getDefaultObject<string>() which would return null and if I were to write getDefaultObject<int>() would return 0.
This question is not merely an academic excercise. I have found numerous places where I could have used this but I cannot get the syntax right. Is this possible? Are there any libraries which provide this sort of functionality?
Well you can't overload anything based only on the return value, so this includes variables.
You can however get rid of that lambda expression and write a real function:
T getDefaultObject<T>() { return default(T); }
and then you call it exactly like you want:
int i=getDefaultObject<int>(); // i=0
string s=getDefaultObject<string>(); // s=null
Though one might find practical workarounds like Stephen Cleary's
Func<T> CreateGetDefaultObject<T>() { return () => default(T); }
where you can specify the generics directly, this is a quite interesting problem from a theoretical point that cannot be solved by C#'s current type system.
A type which, as you call it, is in itself generic, is referred to as a higher-rank type.
Consider the following example (pseudo-C#):
Tuple<int[], string[]> Test(Func<?> f) {
return (f(1), f("Hello"));
}
In your proposed system, a call could look like that:
Test(x => new[] { x }); // Returns ({ 1 }, { "Hello" })
But the question is: How do we type the function Test and it's argument f?
Apparently, f maps every type T to an array T[] of this type. So maybe?
Tuple<int[], string[]> Test<T>(Func<T, T[]> f) {
return (f(1), f("Hello"));
}
But this doesn't work. We can't parameterize Test with any particular T, since f should can be applied to all types T. At this point, C#'s type system can't go further.
What we needed was a notation like
Tuple<int[], string[]> Test(forall T : Func<T, T[]> f) {
return (f(1), f("Hello"));
}
In your case, you could type
forall T : Func<T> getDefaultValue = ...
The only language I know that supports this kind of generics is Haskell:
test :: (forall t . t -> [t]) -> ([Int], [String])
test f = (f 1, f "hello")
See this Haskellwiki entry on polymorphism about this forall notation.
This isn't possible, since a delegate instance in C# cannot have generic parameters. The closest you can get is to pass the type object as a regular parameter and use reflection. :(
In many cases, casting to dynamic helps remove the pain of reflection, but dynamic doesn't help when creating new instances, such as your example.
You can't do this, because generic type parameters have to be known at runtime. You have to use the activator class:
Object o = Activator.CreateInstance(typeof(StringBuilder));
which will do exactly what you want to. You can write it as the following:
public T Default<T>()
{
return (T)Activator.CreateInstance(typeof(T));
}
Edit
Blindy's solution is better.
If you go right now and type string.Format into your IDE, you'll see that there are 4 different overloads: one taking a string and object, another taking a string and two objects, then one taking three objects, and finally one that uses params. According to this answer, this is because params generates 'overhead', and some other languages may not support it.
My question is, why can't a method call like this:
void Foo()
{
Bar(1, 2, 3);
}
void Bar(params int[] args)
{
// use args...
}
Be essentially transformed at compile time to
void Foo()
{
Bar(new[] { 1, 2, 3 });
}
void Bar(int[] args)
{
// use args...
}
? Then it wouldn't create any overhead except for the array creation (which was necessary anyway), and would be fully compatible with other languages.
The number of arguments is already known at compile-time, so what's preventing the C# compiler from doing some kind of string substitution and making the first scenario essentially syntactic sugar for the second? Why did we have to implement hidden language features specifically to support variadic arguments?
The title makes an incorrect assumption.
Both a params and a non-params methods take an array; the difference is the compiler will emit the IL to create an array implicitly when making a params method call. An array is passed to both methods, as a single argument.
This can be seen in this .NET Fiddle (view "Tidy Up -> View IL").
using System;
public class Program
{
public static void Main()
{
var a1 = 1;
var a2 = 2;
var a3 = 3;
with_params(a1,a2,a3);
no_params(new [] {a1,a2,a3});
}
public static void with_params(params int[] x) {}
public static void no_params(int[] x) {}
}
In both cases the IL is identical; a new array is created, it is populated, and the array is supplied to the invoked method.
There is an "exception" to this identical IL generation in that the compiler can move out constant-valued arrays when used in the non-parameter form and use 'dup' initialization, as seen here. However, a new array is supplied as the argument in both cases.