My class currently has two constructors, which are overloads:
public CustomRangeValidationAttribute(string value) {}
and
public CustomRangeValidationAttribute(object value) {}
this appears to be working correctly: When I call the method using a string the first constructor is called, when I use different values, for example an integer or boolean, the second constructor is called.
I assume there is a rule to force specific type matches into the more specific overload, preventing
var c = new CustomRangeValidationAttrubute("test");
from calling the object-overload.
Is this "safe code", or should (or can) the code be improved? I have a nagging feeling this is not the best practice.
You have two overloads which only vary in the reference types and there's a hierarchical relationship between the reference types, such that one may be cast to the other.
In such a circumstance, you really ought to make sure that the code behaves the same logically when the broader overload is selected but the reference turns out to be of the more derived type1,2. That is where to focus your attention. Of course, if you can stick by this rule, often it'll turn out that the more derived overload isn't required and can just be special-cased within the broader method.
1Especially because, as vc74 points out in a comment, overload resolution (generally, ignoring dynamic) is done at compile time based on compile-time types3.
2And this fits the same broad principal for overloads. Don't have overloads where which one is selected leads to logically different results. If you're exhibiting different behaviours, don't give them the same name (for constructors, that may mean splitting into two separate classes, possibly with a shared base class, if that's what you intend to do)
3I appreciate that this is for an attribute and so you're expecting only compile-time to be relevant, but I'd still hew to the general principal here, where possible.
Once there is overload with signature of more derived type the compiler will always choose most concrete type you provide.
That being said, unless someone does new CustomRangeValidationAttrubute((object)"test") if you pass string to CustomRangeValidationAttrubute always constructor with string in it's parameter will be chosen.
About if this is bad practice, I can't tell for sure if I don't see your specific use case, just keep in mind every value type you pass to new CustomRangeValidationAttrubute(object) will be boxed and this is bad as it puts pressure to the GC and whats more you will loose type safety.
The way I resolved this code was by moving the overloads to a new abstract class with separate methods instead of the the original constructors:
public CustomRangeValidationStringAttribute(string value) {}
public CustomRangeValidationGenericAttribute(object value) {}
In the two classes inheriting from this new base class each use their own method, creating two different attributes to choose from, [CustomRangeValidationString] and [CustomRangeValidationGeneric].
You could use a generic class.
See the documentation
class YourClass<T>
{
public YourClass(T value){}
}
Related
In the sample code shown below, the "CompileError" method won't compile, because it requires the where T : new() constraint as shown in the CreateWithNew() method. However, the CreateWithActivator<T>() method compiles just fine without a constraint.
public class GenericTests
{
public T CompileError<T>() // compile error CS0304
{
return new T();
}
public T CreateWithNew<T>() where T : new() // builds ok
{
return new T();
}
public T CreateWithActivator<T>() // builds ok
{
return Activator.CreateInstance<T>();
}
}
Why is this?
According to https://stackoverflow.com/a/1649108/531971, which references MSDN documentation, and this question, the new T() expression in generics is actually implemented using Activator.CreateInstance<T>(). So I don't understand why calling new T() requires that the generic type be constrained in a way that can be omitted when using Activator.CreateInstance<T>().
Or, to put the question the other way around: what's the point of the where T : new() constraint, if it's easy to create instances of T in a generic method without the constraint, by directly using the exact same underlying infrastructure?
There is a conceptual difference between Activator and T():
Activator.CreateInstance<T> — I want to create a new instance of T using its default constructor — And throw an Exception if it doesn't have one (Since something very wrong has happened and I want to handle it/throw it myself).
Side note: keep in mind that as MSDN says:
In general, there is no use for the CreateInstance<T>() generic method in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used.
since generally you would want to use a constructor when the Type is known at compile time (CreateInstance<T>() uses RuntimeTypeHandle.CreateInstance which is slower [Also that's why Activator.CreateInstance<T> itself doesn't need the constraint]).
T() — I Want to call the empty constructor of T, supposedly like a standard constructor call.
You don't want a "standard" constructor call to fail because "No such constructor was found", therefore, the compiler wants you to constraint that there is one.
More than that; You should prefer Compile time errors over Exceptions where possible.
The fact that T() is implemented internally using reflection irrelevant for the average case of "I just want a default instance of T" (of course that the internal implementation is important if you care about performance/etc...).
This is just sugar. Self-control sugar if you can say so. For example, you can call through reflection almost any method in any type (in some cases even without instance!), but this is just not right, don't you agree? Your code will just become unmaintainable at some point, and many errors will pop-up in execution time, this is very bad. So, if you can control yourself before execution - just do it.
Constraint will help you to understand it in compile-time.
The Activator.CreateInstance<T>() method is exposed to user code to allow for the possibility that a generic class might be usable in different ways, some of which would require that the type parameter satisfy certain constraints and some of which don't. For example, a class Foo<T> might support any of the following usage patterns:
Client code supplies a function that returns a new T.
Client code defers to a default function which creates a new T using its default constructor.
Client code avoids using any features of the class that would require it to create new instances of T.
Patterns #1 and #3 should be usable with any T, while #2 should only work with types having parameterless constructors. Having Activator.CreateInstance<T>() compile for an unconstrained T, and work for types T that happen to have parameterless constructors, makes it easy to have code support all three usage patterns. If Activator.CreateInstance<T> had a new constraint, it would be very awkward to use it with generic type parameters that don't have one.
Is it possible to implement a class constrained to two unique generic parameters?
If it is not, is that because it is unimplemented or because it would be impossible given the language structure (inheritance)?
I would like something of the form:
class BidirectionalMap<T1,T2> where T1 != T2
{
...
}
I am implementing a Bidirectional dictionary. This is mostly a question of curiosity, not of need.
Paraphrased from the comments:
Dan: "What are the negative consequence if this constraint is not met?"
Me: "Then the user could index with map[t1] and map[t2]. If they were the same type, there would be no distinction and it wouldn't make any sense."
Dan: The compiler actually allows [two generic type parameters to define distinct method overloads], so I'm curious; does it arbitrarily pick one of the methods to call?
Expanding on the example to highlight the problem:
public class BidirectionalMap<T1,T2>
{
public void Remove(T1 item) {}
public void Remove(T2 item) {}
public static void Test()
{
//This line compiles
var possiblyBad = new BidirectionalMap<string, string>();
//This causes the compiler to fail with an ambiguous invocation
possiblyBad.Remove("Something");
}
}
So the answer is that, even though you can't specify the constraint T1 != T2, it doesn't matter, because the compiler will fail as soon as you try to do something that would violate the implicit constraint. It still catches the failure at compile time, so you can use these overloads with impunity. It's a bit odd, as you can create an instance of the map (and could even write IL code that manipulates the map appropriately), but the C# compiler won't let you wreak havoc by arbitrarily resolving ambiguous overloads.
One side note is that this kind of overloading could cause some odd behaviors if you're not careful. If you have a BidirectionalMap<Animal, Cat> and Cat : Animal, consider what will happen with this code:
Animal animal = new Cat();
map.Remove(animal);
This will call the overload that takes Animal, so it will try to remove a key, even though you might have intended to remove the value Cat. This is a somewhat artificial case, but it's enough to warrant caution when very different behaviors occur as a result of method overloading. In such cases, it's probably easier to read and maintain if you just give the methods different names, reflecting their different behaviors (RemoveKey and RemoveValue, let's say.)
The inequality wouldn't help the compiler to catch errors. When you specify constraints on type parameters, you are telling the compiler that variables of this type will always support a certain interface or will behave in certain ways. Each of those allows the compiler to validate something more like "this method will be present so it can be called on T".
The inequality of type parameters would be more like validating that method arguments are not null. It is part of the logic of the program, not its type safety.
Type constraints seem like a misnomer. While they do contrain what the type parameter is, the purpose is to let the compiler know what operations are available to the type.
If you wanted to, you can have a constraint where T1 and T2 both derive from seperate concrete base classes, but I don't think that's quite what you want.
I'm not entirely sure why this would be a desirable compile time check. It would be possible to essentially by-pass the condition by boxing either the key or the value, thereby rendering the compile-time check useless.
Some consideration needs to be made to determine... what errors am I trying to prevent?
If you are simply stopping a lazy co-worker from not reading the documentation, then add a Debug only check and throw an exception. This way the check can be removed for release code e.g.
#if Debug
if (T1 is T2 || T2 is T1)
{
throw new ArguementException(...);
}
#endif
If you are attempting to prevent a malevolent person from using your library in an unintended way, then perhaps a runtime check is needed, otherwise it would be easy to box the key or value.
No, you cannot use equality (or inequality) as a constraint. Simply put, equality is not a constraint, but a condition. You should test for a condition such as equality or inequality of types in the constructor and throw an appropriate exception.
There is no effective way to do this without imposing any other restrictions on the types themselves. As someone else noted, you could make constraints that the two types derived from two different base classes, but that's probably not very good from a design standpoint.
Edited to add: the reason this is not implemented is most likely because nobody at Microsoft ever considered something like this to be necessary to enforce at compile time, unlike the other constraints which have to do with how you're actually able to use variables of the specified types. And as some commenters have pointed out, you can certainly enforce this at runtime.
For example
int GetNum(int x, int y)
{
return x+y;
}
then call
z= GetNum(myobject.x, myobject.y);
or
int GetNum(ClassA myobject)
{
return myobject.x+myobject.y;
}
then call
z = GetNum(myobject);
Pass in the property values to reduce coupling between your classes. The class that defines GetNum does not need to know about ClassA in this case.
It is better to reduce coupling\dependencies between classes as this makes your design more flexible. Where you do supply complex types to methods, then supply interfaces instead so that you can vary which particular implementation you pass around. This again makes your design more flexible, and more easily testable.
I think this depends very much on your own coding style.
In my opinion, a method should take an object as an argument if the purpose of that method is linked to that object. For instance, a method to format the fields of an object into a pretty text string should take an object as its arguments.
In your example, the method isn't really related to the object - it could take any two numbers, they don't have to be wrapped up in a particular object to work, so I think the method should take properties as arguments.
I don't think it makes a big difference which style you choose, though.
The general rule I follow is this. Does the method require the object?, or does it require property values of the object? The latter makes the method more usable (as it doesn't require users to create an instance of whatever type has these properties).
What you could do, is provide an overload (thus supporting both):
int GetNum(int x, int y) { return (x + y); }
int GetNum(ClassA obj) { return GetNum(obj.X, obj.Y); }
Ask yourself what are the likely use cases for the method, and then ask if you actually require the need to pass in an instance which wraps the values.
Consider that I might have the following method:
public void ProcessMessage(Result result)
{
// Do something with Result.ReturnedMessage
result.ReturnedMessage.Process(result.Target);
}
It accepts a single instance of a theoretical Result type, but the reality is, it's only using two arguments, so we could redefine it as:
public void ProcessMessage(Message message, Target target)
{
message.Process(target);
}
This now makes the method usable in potentially more scenarios, and of course, you could define an overload that just routes from ProcessMessage(Result) to ProcessMessage(Message, Target), etc.
On the other hand, if the method forms part of an interface definition:
void ProcessMessage(Result result);
You can't guarantee that a type implementing that method won't require access to more than just the ReturnedMessage and Target properties.
Bottom line is, consider you use-cases, and how that fits in with the larger design. Also consider future-proofing... how easy is it to spin up our theoretical Result type?
As a footnote, this is a very similar argument as to where to pass a value using a specialised type, or a base type, e.g.:
public void DoSomething(List<string> items);
public void DoSomething(IList<string> items);
public void DoSomething(IEnumerable<string> items);
In the above examples, is your method doing anything that explicitly requires the List<string> type, or will it work with the IList<string> interface definition... or if you are not adding anything at all.. how about accepting an IEnumerable<string> instance instead. The less you specialise your method calls, the more widely they can be used.
In this case as chibacity says GetNum doesn't need to know about ClassA. however, you might consider actually adding GetNum as a method of ClassA which calls GetNum passing in the appropriate values. Its not necessarily write but if you are going to do it a lot it might make sense.
I think, that like everything else interesting, the answer is "It depends".
The example may have been simplified too much, to give enough context to answer the question properly. There seems to be three ways of addressing the solution:
1) int GetNum(ClassA myObject){}
2) int ClassA.GetNum(){}
3) int GetNum(int a, int b) {}
In the past, I would have come down in favour of option 2, making GetNum a member of ClassA. It's none of the caller's business how GetNum works, or where it gets the information from, you (the caller) just want to get a number from a ClassA object. The code of option needs to know about the contents of ClassA, so this is inappropriate, even if it just uses two getters. If we knew more about the context, then maybe option one would be better. I can't tell from the question.
There's a huge interest in improving the testability of code at work, especially legacy code. and unless there's a useful unit testing framework already in place, options 1 and 2 require an object of ClassA, be instantiated for testing. In order to make the code testable (especially if ClassA is expensive or impractical to instantiate) we've been going with something like option 3 (or making it a static member of ClassA). This way, you do not need to instantiate or pass around objects that are difficult to make, AND you can easily add complete code test coverage.
As always though, YMMV.
Is there a name for this pattern?
Let's say you want to create a method that takes a variable number of arguments, each of which must be one of a fixed set of types (in any order or combination), and some of those types you have no control over. A common approach would be to have your method take arguments of type Object, and validate the types at runtime:
void MyMethod (params object[] args)
{
foreach (object arg in args)
{
if (arg is SomeType)
DoSomethingWith((SomeType) arg);
else if (arg is SomeOtherType)
DoSomethingElseWith((SomeOtherType) arg);
// ... etc.
else throw new Exception("bogus arg");
}
}
However, let's say that, like me, you're obsessed with compile-time type safety, and want to be able to validate your method's argument types at compile time. Here's an approach I came up with:
void MyMethod (params MyArg[] args)
{
// ... etc.
}
struct MyArg
{
public readonly object TheRealArg;
private MyArg (object obj) { this.TheRealArg = obj; }
// For each type (represented below by "GoodType") that you want your
// method to accept, define an implicit cast operator as follows:
static public implicit operator MyArg (GoodType x)
{ return new MyArg(x); }
}
The implicit casts allow you to pass arguments of valid types directly to your routine, without having to explicitly cast or wrap them. If you try to pass a value of an unacceptable type, the error will be caught at compile time.
I'm sure others have used this approach, so I'm wondering if there's a name for this pattern.
There doesn't seem to be a named pattern on the Interwebs, but based on Ryan's comment to your question, I vote the name of the pattern should be Variadic Typesafety.
Generally, I would use it very sparingly, but I'm not judging the pattern as good or bad. Many of the commenters have made good points pro and con, which we see for other patterns such as Factory, Service Locator, Dependency Injection, MVVM, etc. It's all about context. So here's a stab at that...
Context
A variable set of disparate objects must be processed.
Use When
Your method can accept a variable number of arguments of disparate types that don't have a common base type.
Your method is widely used (i.e. in many places in code and/or by a great number of users of your framework. The point being that the type-safety provides enough of a benefit to warrant its use.
The arguments can be passed in any order, yet the set of disparate types is finite and the only set acceptable to the method.
Expressiveness is your design goal and you don't want to put the onus on the user to create wrappers or adapters (see Alternatives).
Implementation
You already provided that.
Examples
LINQ to XML (e.g. new XElement(...))
Other builders such as those that build SQL parameters.
Processor facades (e.g. those that could accept different types of delegates or command objects from different frameworks) to execute the commands without the need to create explicit command adapters.
Alternatives
Adapter. Accept a variable number of arguments of some adapter type (e.g. Adapter<T> or subclasses of a non-generic Adapter) that the method can work with to produce the desired results. This widens the set your method can use (the types are no-longer finite), but nothing is lost if the adapter does the right thing to enable the processing to still work. The disadvantage is the user has the additional burden of specifying existing and/or creating new adapters, which perhaps detracts from the intent (i.e. adds "ceremony", and weakens "essence").
Remove Type Safety. This entails accepting a very base type (e.g. Object) and placing runtime checks. Burden on what to know to pass is passed to the user, but the code is still expressive. Errors don't reveal themselves until runtime.
Composite. Pass a single object that is a composite of others. This requires a pre-method-call build up, but devolves back to using one of the above patterns for the items in the composite's collection.
Fluent API. Replace the single call with a series of specific calls, one for each type of acceptable argument. A canonical example is StringBuilder.
It is called an anti-pattern more commonly known as Poltergeist.
Update:
If the types of args are always constant and the order does not matter, then create overloads that each take collections (IEnumerable<T>) changing T in each method for the type you need to operate on. This will reduce your code complexity by:
Removing the MyArg class
eliminating the need for type casting in your MyMethod
will add an additional compile time type safety in that if you try to call the method with a list of args that you can't handle, you will get a compiler exception.
This looks like a subset of the Composite Pattern. Quoting from Wikipedia:
The composite pattern describes that a group of objects are to be treated in the same way as a single instance of an object.
This question gives me curiosity... When you want to define a type you must say GetType(Type) ex.: GetType(string), but ain't String a type itself?
Why do you need to use GetType in those situations? And, if the reason is because it is expecting a Type 'Type'... why isn't the conversion implicit... I mean, all the data is there...
What you're doing is getting a reference to the meta-data of the type ... it might be a little more obvious if you look at the C# version of the API, which is typeof(string) ... which returns a Type object with information about the string type.
You would generally do this when using reflection or other meta-programming techniques
string is type, int is type and Type is type and they are not the same. but about why there is no implicit conversion it's not recommended by MSDN:
By eliminating unnecessary casts,
implicit conversions can improve
source code readability. However,
because implicit conversions can occur
without the programmer's specifying
them, care must be taken to prevent
unpleasant surprises. In general,
implicit conversion operators should
never throw exceptions and never lose
information so that they can be used
safely without the programmer's
awareness. If a conversion operator
cannot meet those criteria, it should
be marked explicit.
Take attention to :
never lose information so that they
can be used safely without the
programmer's awareness
When you want to define a type you must say GetType(Type) ex.: GetType(string)...
That's not true. Every time you do any of the following
class MyClass
{
///...
}
class MyChildClass : MyClass
{
}
struct MyStruct
{
///...
}
you're defining a new type.
if the reason is because it is expecting a Type 'Type'... why isn't the conversion implicit... I mean, all the data is there...
One reason for this is polymorphism. For instance, if we were allowed to do the following:
MyChildClass x;
....GetType(x)
GetType(x) could return MyChildClass, MyClass, or Object, since x is really an instance of all of those types.
It's also worth noting that Type is itself a class (ie, it inherits from Object), so you can inherit from it. Although I'm not sure why you'd want to do this other than overriding the default reflection behavior (for instance, to hide the internals from prying eyes).
GetType(string) will return the same information. Look at it like you would a constant. The only other way to get the Type object that represents a string would be to instantiate the string object and call o.GetType(). Also, this is not possible for interfaces and abstract types.
If you want to know the runtime type of a variable, call the .GetType() method off of it, as the runtime type may not be the same as the declared type of the variable.