This question already has answers here:
Extension method and dynamic object
(3 answers)
Closed 6 years ago.
I have a Extension Function named ParseLong for string.
public static long ParseLong(this string x, long Default = 0)
{
if (!string.IsNullOrEmpty(x))
long.TryParse(x, out Default);
return Default;
}
And works fine:
long x = "9".ParseLong();
However for dynamic objects like:
dynamic x = GetValues();
x.StartValue.ToString().ParseLong();
generates the error:
'string' does not contain a definition for 'ParseLong'
Correct, extension functions do not work for dynamic objects. That is because the dynamic object, when being told to execute ParseLong, has no clue what using directives were in your C# code, so cannot guess what you want to do.
Extension methods are 100% a compiler feature (only); dynamic is primarily a runtime feature (although the compiler has to help it in places).
You could just cast, though, if you know the type:
long x = ((string)x.StartValue).ParseLong();
(which swaps back from dynamic to regular C#, so extension methods work)
Related
This question already has answers here:
Method Overloading with different return type [duplicate]
(9 answers)
Closed 3 years ago.
I would like to overload the return type of a function in C#. In this function a string would be manipulated in a specific way depending on which method is called which I assumed would be determined by the signature of the method of which only the return type is different.
I am fairly new to C# and in Delphi I would have been able to do this (If I remember correctly) so open to suggestion on what would be the best practice here.
public Class1 GetAppSettings()
{
Class1 result = new Class1();
// Code does something
return result;
}
public Class2 GetAppSettings()
{
Class2 result = new Class2();
// Code does something
return result;
}
I am assuming the calling procedure will define what type of return type would be required.
Overloading on the return type is unfortunately not supported. Apparently the return type is not (and indeed can not be) considered for overloading. The compiler can only tell based on the arguments wich one you want.
However there is bunch of other ways:
out parameters. Usually those are only used for outputs if you need to hand additional values out of the function (like with TryParse). But I do think this should be compileable and allow overloading:
public void GetAppSettings(out Class1 output)
{
Class1 result = new Class1();
output = result;
}
Another way should be extension Methods, but those might be too limited. And after all you are writing those classes right now, so they are unnecessary. I only mention them for completeness.
And of course it could be that you never wanted different implementations to begin with (wich is a core focus of overloading), in wich case generics are the way to go.
This question already has answers here:
Solution for overloaded operator constraint in .NET generics
(4 answers)
What are generics in C#? [closed]
(3 answers)
Closed 6 years ago.
Generics are used to decouple logic from data type.
public class Calc<T>
{
public T Add(T a, T b)
{
return (a+b);
}
}
But this is throwing the below compile time error
Operator + cannot be applied on type T.
I am not understanding why so. because if it allows from main.cs
main()
{
Calc<int> obj = new Calc<int>();
int c = obj.Add(10,20);
}
Can somebody please explain why I am getting Build errors??
C# generics don't support arbitrary operators. The exact (possibly virtual) method must be known at compile-time of the generic type. Since the generic type argument in your example isn't constrained at all, you can only use the members of the object type, which doesn't include a + operator.
There's no way to use C# generics to do what you're trying to do, sorry. The best you can do is a bunch of type-checks for a few known types (and the appropriate casts, which are tricky with value types), or using reflection (dynamic in particular will work great).
Unrestricted generics like your Calc<T> must be able to compile with any type applied, not all types support the + operand so your code does not compile. This is regardless of what specific types you create your calling code with.
You can restrict the type of T and thus gain access to more methods by doing Calc<T> where T:object or Calc<T> where T: IComparable which would allow you to:
public T CompareTo(T a, T b)
{
return (a.CompareTo(b));
}
Since all T must now implement IComparable. Unfortunately Int32 does not implement any interface which defines the + operator or any addition method. So there is no way to implement that statement you are trying.
C# generics are different from C++ templates. The C# code cannot be compiled if generic type doesn't have definition for used method (operator+ in your case), while C++ compiler applies this method to the actual template argument type.
Addition is not allowed because there is no guarantee that passed types have operator + overload.
There is a way to accomplish that but it will work as long as you pass types that have operator +. Otherwise, RuntimeBinderException will be thrown. Also, there is some impact on performance, but unless code is performance critical, shouldn't be a problem.
public T Add<T>(T a, T b)
{
dynamic da = a, db = b;
return da + db;
}
This question already has answers here:
Extension method and dynamic object
(3 answers)
Closed 7 years ago.
I am trying to call IEnumerable.Contains() with a dynamic argument, but I am getting the error
'IEnumerable' does not contain a definition for 'Contains' and the best extension method overload 'Queryable.Contains(IQueryable, TSource)' has some invalid arguments
I've noticed that I can either cast the argument to the correct type, or use an underlying collection type to fix the issue. But I'm not sure why I can't just pass in the argument directly.
dynamic d = "test";
var s = new HashSet<string>();
IEnumerable<string> ie = s;
s.Contains(d); // Works
ie.Contains(d); // Does not work
ie.Contains((string)d); // Works
Enumerable.Contains is an extension method - and extension methods aren't resolved by the mini-compiler which is used at execution time. (Extension methods depend on using directives, which aren't preserved. They could be, but I guess that was seen as a bit painful.) This includes both using dynamic arguments to extension methods, and on using them as the "target" of extension methods.
Just specify the extension method directly instead:
var result = Enumerable.Contains(ie, d);
This question already has answers here:
Method overload resolution with regards to generics and IEnumerable
(2 answers)
Closed 8 years ago.
So, I'm having an issue with similar code to below:
public static String MyFunc<T>(this IEnumerable<T> list) where T : struct
{
... some code ...
return myString;
}
public static String MyFunc<T>(this T o) where T : struct
{
... some code ...
return myString;
}
The problem is that when trying to do call MyFunc on a List it uses the second function instead of the one that accepts an IEnumerable. I know this has to do with variance, but I'm uncertain as to how to force it to use the first function rather than the second. The code I would use to call the first one would be:
List<int> x = new List<int>();
String s = x.MyFunc();
The above code immediately goes to the second function and I need it to use the first. How can I force the desired behavior? Incidentally, I'm using .NET 4.0
The reason that it's currently picking the second method is that a conversion from a type to itself (second method, T=List<int>, conversion from List<int> to List<int>) will always be "better" than a conversion to the type it implements (first method, T=int, conversion from List<int> to IEnumerable<int>). This has nothing to do with variance, by the way - it's just the method overloading algorithm and type inference.
Note that with your current code, although the second overload is picked, it will then be found to be invalid because T violates the T : struct constraint. The constraint is only checked after the overload is chosen. See Eric Lippert's blog post on this for more details.
I suggest you just give the two methods different names.
EDIT: As noted by Anthony in comments, this can work if you call it as:
x.AsEnumerable().MyFunc();
Or just change the declaration to:
IEnumerable<int> x = new List<int>();
x.MyFunc();
It's not entirely clear to me exactly why it's better here - in this case after type argument substitution, you've basically got IEnumerable<T> as the parameter type in both cases. However, I would still strongly recommend using different names here. The fact that it's got me puzzling over the spec to work out which overload is being called should be enough indication that the behaviour won't be immediately clear to everyone reading the code.
EDIT: I think the reason is here (from the C# 5 spec, section 7.5.3.2):
A type parameter is less specific than a non-type parameter
So just T is less specific than IEnumerable<T>, even though the latter involves a type parameter. It's still not clear to me whether this is the language designers' intended behaviour... I can see why a type which involves type parameters should be seen as less specific than a type which doesn't involve type parameters, but not quite this wording...
This question already has answers here:
LINQ .Cast() extension method fails but (type)object works
(3 answers)
Closed 9 years ago.
I recently had a problem using it user-defined casts (cast operator overload) alongside linq's Cast method.
I found a similar question about my problem here at SO and I also found a link that explains it well. My problem is solved.
But something kept me wondering:
Why this doesn't work:
foolist.Cast<bar>(); // throws InvalidCastException
while this works:
foolist.Select(f => (bar)f).ToList(); // works fine
I believe that it's something related to the implementation of each method. If so, couldn't the Cast method have a similar implementation to Select allowing it to be used with user-defined casts (since this is somewhat expected).
Note: I'm not asking why it fails. I'm asking why the Cast method was written in a way that fails.
The reason why is that the Cast method performs the cast in a generic context
IEnumerable<T> Cast<T>(this IEnumerable e) {
foreach (object cur in e) {
return (T)cur;
}
}
The actual casting logic is verified and emitted at this exact point. This point is in a generic function and has no knowledge of the user defined conversions for the type T is eventually instantiated into. All it has access to is standard CLR style conversions.
In the second example you are doing a cast on the real type (not a generic type parameter). Hence the C# compiler has access to all user defined conversions on that object and can insert the most appropriate one.