I have an API which includes some methods that take in a type parameter. I am now converting them to generic methods as part of improving the API (more type-safe), while keeping the non-generic version around for backward compatibility.
Current - to be obsoleted:
public object MyMethod(object value, Type expectedType)
New:
public T MyMethod<T>(object value)
However, Mymethod calls a private helper method which also takes in a type parameter:
private object HelperMethod(object value, Type expectedType)
Question: should I also make this private helper method generic?
I have my own answer below, but I would like to know if I'm missing something. I appreciate your insights very much.
My answer is no, I should not make this private method generic.
Reason 1: this helper method is private, so even if I made it generic, it doesn't improve the API.
Reason 2: If I make it generic, then the non-generic public methods will have to use reflection to pass the type parameter to this generic method, which means more overhead.
Making your private helper method generic does improve the API by carrying the generic type-specificity all the way through your implementation. Your implementation isn't fully realizing the type safety benefits of generics if you throttle the type down to a core that juggles typeless System.Objects around.
For example, why is the parameter to MyMethod still a System.Object? If that parameter originates in source, chances are good that it should be a type parameter too. If the parameter originates in data, you're probably better off with System.Object. Generics are most useful when they are used with source code, because source code expressions implicitly provide the type in most contexts.
The hidden costs of generics depends on the mix of types that will be used with the API. If most of the types will be value types (built-ins and structs), then switching the API to generics could raise your memory consumption because the generic code must be jit'd differently for each value type. If the majority of types used with your generic API are reference types (classes and interfaces), code/memory explosion isn't a concern because all reference types share the same JIT'd code.
Whether the cost of having the old API call the new generic API is a) measurable and b) acceptable depends entirely upon what you're doing in your private helper method - in particular, what the private helper method does with the Type parameter.
If the helper method implementation is fairly lightweight and you determine (by performance measurements) that the cost of adapting the old API to call the new generic helper is unacceptable, I would consider duplicating the helper method implementation, side by side, one in the old style and one in the new generic style. This eliminates crossover conversion costs between the API styles and eliminates the risk of introducing new bugs into the old API, at the cost of slightly increased internal code maintenance efforts.
I think it depends on the amount of time you plan to support the non-generic method, how often it will be called, what the impact on the reflection will be, etc. etc.
I would think you would want the generic functionality as much as you can to take advantage of the type-safety you want. Then retro-fit the non-generic version to use the generic version if necessary, and eventually deprecate it as soon as you can.
Related
For a generic class, foo<T> I can specify methods that only are available to certain types of the class, for example
public static void(this foo<int> val) is a valid declaration, as is
public static void(this foo<float> val) and in this way, I can specify different behaviors for a generic I intend to use the same way, handling the difference between them in their individual methods. Most useful case of this is to add Arithmetic functions to Vectors, Matrices, and Sets while still having them generic. (Since there is for some god forsaken reason still no INumeric constraint to define only types which support the basic operators)
Is there an equivalent functionality for static variables. The objective being, I can accomplish the following:
foo<int>.Zero and foo<float>.Zero and have each one be different, and not conflict with each other, returning a foo of the appropriate type, but without throwing errors in the case where foo<bar>.Zero because there is no "Zero" concept for an object like bar
C# does not provide with syntax that allow you to define field for property extensions, or static extensions for classes.
To achieve this, you should use some static property like foo.ZeroOfFloat as some C# standard APIs are defined like that.
It looks very pretty and cleaned when you are using more generic things, but this is not the correct use case of generic.
"Generic" means that it is general, for type irrelavent use, therefore it is different from template definitions in C++ that supports specialization. Technically, generic definitions in C# is compiled and delivered as IL, rather than as source code in C++, which means the compilation happens before a certain type is plugged into a generic definition and there cannot be a specialization for a single type.
Although there are some generic constraints for reference types, value types, delegates, or native structs etc., that limit the use of generic definition to some type of types. This disallows some use cases, rather than supporting something.
Although you could make use of that there could be different extension methods on a generic type that is closed with different type arguments (that gives you a feeling of template specialization), that is not by design.
Do not achieve a specific logic in generic definition. Definitions like ZeroOfFloat are never bad practices.
I have a piece of code like the following:
public class ActivityHelper
{
public void SetDate(IList<Activity> anActivityList)
{
foreach(Activity current in anActivityList)
{
current.Date = DateTime.Now;
}
}
//More methods, properties, fields, etc...
}
This could easily be converted to an extension method. For example:
public static void SetDate(this IList<Activity> aList)
{
foreach(Activity current in anActivityList)
{
current.Date = DateTime.Now;
}
}
The original function doesn't use any instance specific data or methods from the ActivityHelper class which makes it seem like it is in the incorrect place. Is this the correct time to write an extension method? What are the correct scenarios in which to create extension methods?
Brad Adams has written about extension method design guidelines:
CONSIDER using extension methods in any of the following scenarios:
To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface. This is because concrete implementations cannot otherwise be assigned to interfaces. For example, the LINQ to Objects operators are implemented as extension methods for all IEnumerable types. Thus, any IEnumerable<> implementation is automatically LINQ-enabled.
When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.
I think Extension methods are only appropriate if there is a compelling reason to make the method an extension method.
If the type is one you do not control, and the method should appear to be integral to the type, or if there is a compelling reason to not put the method directly on the type (such as creating an unwanted dependency) then an extension method could be appropriate.
Personally, if the expectation of the user of your API will already be to use the "ActivityHelper" class when working with collections of Activities, then I would probably not create an extension method for this. A standard, non-extension method will actually be a simpler API, since it's easily understood and discoverable. Extension methods are tricky from a usage standpoint - you're calling a method that "looks like" it exists somewhere other than where it actually exists. While this can simplify syntax, it reduces maintainability and discoverability.
In my experience extension methods work best when they:
Don't have side-effects (most of the extension methods my team wrote that have side-effects, we ended up removing because they caused more problems than they helped)
Offer functionality that applies to every possible instance or value of the type they're extending. (Again citing an example from my team, string.NormalizeUrl() is not appropriate because not all strings are even URLs anyway)
Well i usually create extension methods to help me write codes which have a smooth flow. Its generally depends upon the method you are creating.
If you feel that the method should have already been in framework and is too general then its okay to create an extension method for that.
But you need to first analyze that the class you are extending will always will be in state that your extension method can handle.
For Guidelines here to Brad's Article
http://blogs.msdn.com/b/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx
In essence, Extension Methods provide a more fluent style syntax for Helper methods. This translates into the ability to seemingly add functionality to types or all implementations of interfaces.
However, I generally steer away from declaring Extension Methods with a void returntype, as I feel the usefulness of this fluent style syntax, which allows you to compose statements, is negated when the method in question doesn't return anything.
However, I guess it can be handy to have your methods picked up by IntelliSense... :-)
I've been studying code of some different libraries, and notice that some will provide equivalent generic and non-generic functions in the same class.
One example is the IServiceLocator interface of the Common Service Locator project:
public interface IServiceLocator
{
object GetInstance(Type serviceType);
object GetInstance(Type serviceType, string key);
IEnumerable<object> GetAllInstances(Type serviceType);
TService GetInstance<TService>();
TService GetInstance<TService>(string key);
IEnumerable<TService> GetAllInstances<TService>();
}
The impression I get is that this is for maximizing accessibility, perhaps from COM. Absent those concerns, this seems like redundant code. Is there anything I'm missing?
Sometimes you know the type you need at compile time, at which point generics can give you compile-time safety and neater code.
Sometimes you only know the type you need at execution time, at which point generics become a pain in the neck, because you need to call them via reflection.
Providing both options gives the flexibility to handle both situations as well as possible.
Probably because the generic type is better for syntax and users will prefer it since it can cast it to the correct type, but for example, if the type is looked up at run time using reflection, you can't use the generic option and need to use the one that takes a Type.
In addition, generics are always resolved at compile time. Think of it as using the generic one when you know the type at compile time, and the non-generic during runtime.
The reason is the non-Generic will use an implied generics by checking its type so that you do not have to mention the type.
For example IEnumerable<T> interface:
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
In this interface the generic type is used only as a return type of interface method and not used as a type of method arguments thus it can be covariant. Giving this, can't compiler theoretically infer the variance from the interface? If it can, why does C# requires us to set co/contravariance keywords explicitly.
Update: As Jon Skeet mentioned this question can be spited into sub-questions:
Can compiler infer generic type's co/contravariance by how it is used inside current generic type and all it's base types?
For example.. How many generic interface parameters from .NET Framework 4.0 can be marked co/contravariant automatically without any ambiguity? About 70%, 80%, 90% or 100%?
If it can, should it apply co/contravariance to generic types by default? At least to those types which it is capable to analyze and infer co/contravariance from the type usage.
Well, there are two questions here. Firstly, could the compiler always do so? Secondly, should it (if it can)?
For the first question, I'll defer to Eric Lippert, who made this comment when I brought exactly this issue up in the 2nd edition of C# in Depth:
It's not clear to me that we reasonably could even if we wanted to. We can easily come up
with situations that require expensive global analysis of all the interfaces in a program
to work out the variances, and we can easily come up with situations where either it's
<in T, out U> or <out T, in U> and no way to decide between them. With both bad
performance and ambiguous cases it's an unlikely feature.
(I hope Eric doesn't mind me quoting this verbatim; he's previously been very good about sharing such insights, so I'm going by past form :)
On the other hand, I suspect there are still cases where it can be inferred with no ambiguity, so the second point is still relevant...
I don't think it should be automatic even where the compiler can unambiguously know that it's valid in just one way. While expanding an interface is always a breaking change to some extent, it's generally not if you're the only one implementing it. However, if people are relying on your interface to be variant, you may not be able to add methods to it without breaking clients... even if they're just callers, not implementers. The methods you add may change a previously-covariant interface to become invariant, at which point you break any callers who are trying to use it covariantly.
Basically, I think it's fine to require this to be explicit - it's a design decision you should be making consciously, rather than just accidentally ending up with covariance/contravariance without having thought about it.
This article explains that there are situations that the compiler cannot infer and so it provides you with the explicit syntax:
interface IReadWriteBase<T>
{
IReadWrite<T> ReadWrite();
}
interface IReadWrite<T> : IReadWriteBase<T>
{
}
What do you infer here in or out, both work?
I have an interface method
public void Execute(ICommand command);
which needs to pass known subtypes of ICommand to an apropriate Handle(SpecificCommand command) method implementation and do some generic handling of unknown types. I am looking for a universal (i.e. not requiring a giant switch) method of doing so, something similar to
Handle(command as command.GetType()); // this obviously does not compile
I know I could register the handlers somehow, e.g. store them as delegates in a dictionary, but this still requires duplicating the handling logic (once in the specific Handle(...) method signature, once in the delegate reqistration). If I populate the dictionary by inspecting my class with reflection (looking for Handle(XXX command) methods), I'll get a performance hit.
To summarize: how can I downcast an object (upcasted by the call to Execute(ICommand command)) to invoke a method requiring a concrete type without knowing which type it is at compile time.
Well, the "correct" answer is that Handle() should be a method in ICommand, so that instead of Handle(command), you'd be saying command.Handle().
The cast is emitted at compile-time, so you need to know the type at compile-time. The overloading is also determined at compile-time - so by the time you actually know the concrete type to use, it's too late.
I don't see that you'd actually be duplicating any logic by using delegates. Alternatively, if you do it with reflection, you can build delegates very easily using Delegate.CreateDelegate - you'll only get a performance hit once, and after that it'll be very fast. See my blog entry about Delegate.CreateDelegate for more information.
I think I'd decide to use a hand-built dictionary or one built with reflection based on how many methods I had and how often they change. You'll probably find KeyedByTypeCollection useful for the dictionary.
You can't, and why would you want to?
That's the whole reason we have polymorphism. If you want to have custom behaviour that is specific to certain types, then the behaviour should live in the type itself and be invoked via a function declared in the base class type.
I've tried working out a way which would work using Double Dispatch (http://en.wikipedia.org/wiki/Double_dispatch), but it seems that you have a situation where the number of classes implementing ICommand and those implementing Execute() can vary at run-time (or, at least between compile & run-time, which is essentially the same thing), so the only solution I can see it use the dictionary as Jon Skeet propsed.