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.
Related
This question already has answers here:
Can anonymous class implement interface?
(9 answers)
Closed 6 years ago.
I am trying to cast anonymous type with the same property to an interface, but it's coming up with an error:
Unable to cast object of type '<>f__AnonymousType104`1[System.Int32]' to type 'IHasFiles'.
public interface IHasFiles
{
int FileMasterId { get; }
}
var entity = new { FileMasterId = fileMasterId }.CastOrDefault<IHasFiles>();
// This is the line where I get the error
That is because interface implementation is explicit, not dynamic.
You can't cast an object to an interface reference simply because it has the same members, the type of that object has to explicitly implement the interface as well.
Anonymous types aren't castable to anything, other than object, dynamic (an object in disguise) or its own type, which is also a bit tricky since you don't exactly know the type (but there are ... hacks for this).
So no, you can't do that.
What you're looking for is commonly known as "duck typing", aka "if it walks like a duck, and if it quacks like a duck, then for all intents and purposes, it is a duck". This is not supported with stock C# or .NET but can be "mimicked" using code.
If you require an object that implements a specific interface you must declare a normal named type that implements the interface, there is no (good) way around it.
Now, this post is only, up until here, referring to the bit that the C# compiler and/or .NET will allow you to do. There is another concept in play here as well that, even if the C# compiler allowed you to do this, would make the concept shady.
And that is intent.
An interface does the following:
Declare a contract about what implementors has to supply of members
Declare a contract about what users can expect of members to be available
Declare a contract about the meaning of those members
This last part is hard to impose onto a type even if you could thread an interface over its head. If I write a class that just happens to have the same members that one of your interfaces, if you were to thread that interface onto my class, could you impose the same meaning of those members?
No, you can't.
Now, obviously, there are ways around it but none that are easy and I would say that in most cases they would be hacks that hide poor design.
In any case, to circumvent this you could, via reflection, build up another type that simultaneously wraps and delegates all members to the type of your object, as well as implement this interface, at runtime.
Is it good design? No, definitely not.
If you really want to go down this route you can, as commented below, use the "ImpromptuInterface" nuget package, and your code would then look like this:
var entity = new { FileMasterId = fileMasterId }.ActLike<IHasFiles>();
But I would strongly advice against this. Declare the type!
I've been looking into empty interfaces and abstract classes and from what I have read, they are generally bad practice. I intend to use them as the foundation for a small search application that I am writing. I would write the initial search provider and others would be allowed to create their own providers as well. My code's intent is enforce relationships between the classes for anyone who would like to implement them.
Can someone chime in and describe if and why this is still a bad practice and what, if any alternatives are available.
namespace Api.SearchProviders
{
public abstract class ListingSeachResult
{
public abstract string GetResultsAsJSON();
}
public abstract class SearchParameters
{
}
public interface IListingSearchProvider
{
ListingSeachResult SearchListings(SearchParameters p);
}
}
Empty classes and interfaces are generally only "usably useful" as generic constraints; the types are not usable by themselves, and generic constraints are generally the only context in which one may use them in conjunction with something else useful. For example, if IMagicThing encapsulates some values, some implementations are mutable, and some aren't, a method which wants to record the values associated with an IMagicThing might be written something like:
void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...}
where IIsImmutable is an empty interface whose contract says that any class which implements it and reports some value for any property must forevermore report the same value for that property. A method written as indicated could know that its parameter was contractually obligated to behave as an immutable implementation of IMagicThing.
Conceptually, if various implementations of an interface will make different promises regarding their behaviors, being able to combine those promises with constraints would seem helpful. Unfortunately, there's a rather nasty limitation with this approach: it won't be possible to pass an object to the above method unless one knows a particular type which satisfies all of the constraints, and from which object derives. If there were only one constraint, one could cast the object to that type, but that won't work if there are two or more.
Because of the above difficulty when using constrained generics, it's better to express the concept of "an IMagicThing which promises to be immutable" by defining an interface IImmutableMagicThing which derives from IMagicThing but adds no new members. A method which expects an IImmutableMagicThing won't accept any IMagicThing that doesn't implement the immutable interface, even if it happens to be immutable, but if one has a reference to an IMagicThing that happens to implement IImmutableMagicThing, one can cast that reference to the latter type and pass it to a routine that requires it.
Incidentally, there's one other usage I can see for an empty class type: as an identity token. A class need not have any members to serve as a dictionary key, a monitor lock, or the target of a weak reference. Especially if one has extension methods associated with such usage, defining an empty class for such purpose may be much more convenient than using Object.
If I have a class like this: -
static class Foo {
public static void Bar<T>(T item) { Console.WriteLine(item.ToString(); }
}
I know that in this example it's unnecessary to use T since all Types have ToString() on them etc. - it's simply a contrived example. What I'm more interested in is what happens under the bonnet in terms of the following: -
Foo.Bar("Hello");
Foo.Bar(123);
Foo.Bar(new Employee("Isaac"));
I broadly (think!) I understand reification i.e. if you make different types of a generic class e.g.
List<Int32>
List<String>
List<Employee>
etc. then at compile-time (or runtime?) we end up with three actual concrete types, one for each generic argument specified. Does the same apply to method calls in my first example i.e. would we still have a single class Foo but three reified Bar methods, one for String, Int32 and Employee?
This is where the difference between C++ templates and C# generics comes into play.
In C++, templates cause a new method to be generated for each type it is used with. In C#, however, the code in the method is only created once. The same code runs whether you call it with an int, string, or object type parameter.
Because C# generics remain generic when compiled, they can be exposed in compiled libraries without need for re-compilation. In C++, you are required to include the original template in your consuming code, so a new copy can be compiled.
Simply put, you only get one compiled method per generic method.
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.
In the code below the "Move" public class derives fromthe generic type "Submit". "Submit" is a method, part of the DSS model, which handles messages and accepts two parameters, one is the message body and one is the message response.
My question is: How or WHY does a class derive from a method?!
It seems to me (since i'm only a beginner) "generic types" mean just this... any method or class (and by extension, any "block" of code) can become a type. Moreover there are NO types... everything is just a "class" which you can derive from (yet you probably can't overload string)
This basicly means that there are in fact NO methods OR types, but rather just classes (and some "sub"classes (ex-methods)) and you can derive from everything?!
Thank you.
I'm not looking for the expert "except this" answear where some small thing is not possible. I would like confirmation that this is, in fact, what 90% of the time, programmers are doing.
public class Move : Submit<MoveRequest, PortSet<DefaultSubmitResponseType, Fault>>
{
public Move()
{
}
public Move(MoveRequest body) : base(body)
{
}
}
You can not derive from a method. Submit<T, V, E> must be a class.
in a little more detail, Submit may be an "action" and therefore commonly thought of as a method, but in your context, Submit is indeed a class. This may be an example of the "Command" design pattern, in which a request for an action is encapsulated in an object and thus can be passed around and acted on by classes that handle the command.
Generics, conceptually speaking, are classes that are able to provide similar functionality among a set of "inner" types. The basic example is a Math class that can add, subtract, multiply and divide two variables of numeric type; you know, very advanced math you can't do any other way. There are a lot of numeric types in most type systems (in C# you have byte, short, int, long, float, double, and decimal, plus unsigned variations). Rather than implement a MathByte, MathInt, MathLong, etc with methods strongly defining the type they work on, or implementing a Math class that works with any Object (and thus requires you to examine the type of everything passed in to determine that you can work with the type), you can simply create a Math<T> class, where T can be any of the numeric types.
The type parameter T is different from method parameters; when you declare an instance of the class, you specify a type that the instance will be set up to handle. That instance can then only work with objects of the specified type, but you can instantiate a Math<byte> and a Math<decimal> to work with different types. Methods defined in Math specify input parameters of type T, and T is "replaced" at instantiation with the type declared when you instantiate the class.
Generics help support the DRY ("Don't Repeat Yourself") tenet of good coding practice, while maintaining type integrity. MathLong, MathInt, MathByte etc would all be similar or identical in their internal code; the main difference would be the type of the object they work on. Instead of rewriting the same class 10 times, you write one class that can be more concretely defined as to its working type by consumers of your class.
Hope this is a little more educational.
No, Submit is definitely not a method. A Class can only derive from another class, or implement an interface. So, Submit has to be either a class or an interface.