C# - How are we supposed to implement default(T) in Interfaces? - c#

Put default(T) in an interface. Explicitly implement the interface. The result does not compile
public interface IWhatever<T>
{
List<T> Foo(T BarObject = default(T));
}
public class ConcreteWhatever: IWhatever<ConcreteWhatever>
{
List<ConcreteWhatever> Foo(ConcreteWhatever BarObject = default(T)) {}
}
I fully expect default(ConcreteWhatever). What I get is default(T) which results in a compilation error.
I just go in and replace default(T) with null and things are fine. But this is hideous. Why is this happening?

You don't have a T in this case, because ConcreteWherever isn't a generic type.
If you want default(ConcreteWhatever) then that's the code you should write.
Are you just complaining about the code auto-generated by Visual Studio? If so, that's a reasonable complaint, but it would be worth being explicit about it... (Note that you're not using explicit interface implementation here - otherwise it would be declared as IWhatever<ConcreteWhatever>.Foo. You don't really have properly implicit implementation either, as otherwise it should be public...)
EDIT: I've just tried the same thing myself, and seen the same result, except the method is made public. Looks like it's just a fault with Visual Studio - I suggest you create a Connect request for it. It's a relatively rare situation though, I suspect - creating a generic interface which specifies an optional parameter which uses the default value of a type parameter as the value...

Shouldn't this line:
List<ConcreteWhatever> Foo(ConcreteWhatever BarObject = default(T)) {}
be:
List<ConcreteWhatever> Foo(ConcreteWhatever BarObject = default(ConcreteWhatever)) {}

public interface IWhatever<T>
{
List<T> Foo(T BarObject = default(T));
}
public class ConcreteWhatever : IWhatever<ConcreteWhatever>
{
public List<ConcreteWhatever> Foo(ConcreteWhatever BarObject = default(ConcreteWhatever))
{
return null; // replace with proper code
}
}

Related

Generic Comparer for all objects with a Text property

I am trying to implement a generic comparer (for a sort) for all objects that have a Text property... so two ASP.net textboxes can be compared, two labels or in this specific case two RadTreeNodes in a telerik RadTreeView (as long as they have a Text property). So I've put the following together to try and so this but get an error as follows:
I have the following code:
public class TextComparer<T> : IComparer
where T : IHasTextProperty
{
public int Compare(object a, object b)
{
T nodeA = (T)a;
T nodeB = (T)b;
return nodeA.Text.CompareTo(nodeB.Text);
}
}
public interface IHasTextProperty
{
string Text { get; set; }
}
Then plan on using it like so...
Array.Sort(nodes, new TextComparer<RadTreeNode>());
but get the following message :
Error 6613 The type 'Telerik.Web.UI.RadTreeNode' cannot be used as
type parameter 'T' in the generic type or method 'TextComparer'.
There is no implicit reference conversion from
'Telerik.Web.UI.RadTreeNode' to 'IHasTextProperty'
I'm sure this is a simple fix, but I'm just a little stumped as to how to fix it.
You are attempting to perform duck-typing in C#, which doesn't support duck-typing. In some languages, you can match a type based on it having a certain property, such as Text in this case. This only works if the language supports this technique.
With C#, a class must explicitly implement an interface for it to be deemed to have that interface's type. Telerik.Web.UI.RadTreeNode doesn't implement IHasTextProperty. T is contrained to types that implement IHasTextProperty, and so you get the error you see.
You really can't use generics in this case. You need to test whether a and b have a Text property. This can be done using reflection or by using dynamic. Neither solution will be as neat as what you were attempting to do unfortunately.
System.Web.UI provides its own IHasTextProperty namely ITextControl (msdn), which behaves exactly like your IHasTextProperty. The downside is that you can not be sure RadTreeNode (or any other 3rd party control) implements this interface.
The only way to be sure is to remove this check from compile time and put it into runtime via reflection, which is quite simple but perhaps not what you want. In case you still want to use it here's an example using an ArgumentException in the TextComparer's constructor to ensure only valid objects are compared.
public class TextComparer<T> : IComparer
{
private bool HasTextProperty(Type t)
{
return (t.GetProperty("Text", typeof(string)) != null);
}
private string GetTextPropertyValue(object obj)
{
return obj.GetType().GetProperty("Text", typeof(string)).GetValue(obj) as string;
}
public TextComparer()
{
if (!HasTextProperty(typeof(T))) throw new ArgumentException(string.Format("{0} doesn't provide a Text property", typeof(T).Name), "T");
}
public int Compare(object x, object y)
{
return GetTextPropertyValue(x).CompareTo(GetTextPropertyValue(y));
}
}

Why can I not infer an interface from a constrained generic collection?

I have a piece of code that works like this:
public IEnumerable<ICacheMember> Flubvert( IEnumerable<ICacheMember> members )
{
// do some stuff to members
return members;
}
However I am confused as to why I can't do this:
public IEnumerable<T> ExecuteFlubversion<T>( IEnumerable<T> memberList ) where T: class,ICacheMember
{
return Flubvert( memberList );
}
Surely the constraint on the generic should guarantee that memberListis an IEnumerable of the ICacheMembertype? Do I really need to convert a collection of existing ( but implicit ) ICacheMember objects into explicit ICacheMember objects and then convert them back afterwards? I can understand that I might need to convert them back given the method signature of Flubvert but I don't see why I should have to convert them in the method call. This is what I am doing in the working code but it seems completely out of keeping with the generally elegant behaviour of generics so I think I must be misunderstanding something about how this is supposed to operate.
First of all covariance of IEnumerable<out T> (and other generic types) only works when T is a reference type, so you need:
public IEnumerable<ICacheMember> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T: class, ICacheMember // NOTE 'class'
{
var flub = Flubvert(memberList); // can you call with 'memberList'?
return flub; // can you return that type?
// depending on what 'Flubvert' does, maybe return 'IEnumerable<T>'
// and say:
// return (IEnumerable<T>)flub;
}
Also note that I changed the return value. The C# compiler cannot guarantee that the returned object from the non-generic Flubvert method is anything more specific than IEnumerable<ICacheMember>.
Lets say you have:
interface ICacheMemberSub : ICacheMember
{
...
}
And you call your function like this:
ExecuteFlubversion<ICacheMemberSub>(cacheMember);
This function will try to return an object with type IEnumerable<ICacheMember>, and that is not necessarily castable to IEnumerable<ICacheMemberSub>, hence the error.
At risk of not directly answering the question, can you change the signature of Flubvert to a generic? If you make Flubvert generic, the rest of the method code will stay the same and you can still assume that the members will be implementers of ICacheMember.
public IEnumerable<T> Flubvert<T>(IEnumerable<T> members)
where T : class, ICacheMember
{
// do some stuff to members
return members;
}
public IEnumerable<T> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T : class,ICacheMember
{
return Flubvert(memberList);
}

C# casting generic parameter to interface

I need help with casting generic paremetrs down to an interface.
I have prebaked code like this:
public interface InterFoo<T> {...}
public InterFoo<T> specialFoo<T>() where T : InterFoo<T> {...}
public InterFoo<T> regularFoo<T>() {...}
and i want to implement something like this
public InterFoo<T> adaptiveFoo<T>()
{
if (T is InterFoo<T>)
return specialFoo<T as InterFoo>();
return regularFoo<T>();
}
at this point I cant find any solution so anything would be helpful, thanks.
EDIT: originally the functions had returned an int but that has a simpler solution that is incompatible with the code's intended purpose, the functions have been changed to request a generic type.
The is and as operators only compile for types that the compiler knows can be null (nullable value types or reference types).
You can try a call to IsAssignableFrom:
public int adaptiveFoo<T>()
{
if (typeof(InterFoo<T>).IsAssignableFrom(typeof(T))
return specialFoo<InterFoo>();
return regularFoo<T>();
}
** Update to reflect changes in question **
Type constraints are, unfortunately viral, in order for your method to compile (when keeping with strict type checking from the compiler) you would need the constraint to be added to this method also. However, reflection can circumvent this restriction:
Your method would be:
public InterFoo<T> adaptiveFoo<T>()
{
if (typeof(InterFoo<T>).IsAssignableFrom(typeof(T))
{
var method = typeof (Class1).GetMethod("specialFoo");
var genericMethod = method.MakeGenericMethod(typeof(T));
return (Interfoo<T>)method.Invoke(this, null);
}
return regularFoo<T>();
}

Adding generic constraints at runtime?

I'm pretty stumped with this so if anyone has any ideas. I have the generic method
public void Foo<TClass>(TClass item) where TClass : class
{ }
And I want to call this method from another generic method, but this generic method doesn't have the type constraint "where TClass : class"
public void Bar<T>(T item)
{
this.Foo<T>(item);
}
This doesn't work, I get the error
"The type 'T' must be a reference type in order to use it as parameter 'TClass'"
Which I understand. But my question is this - is there anything I can do with C# syntax in order to "filter" the generic type "T" to pass it to "this.Bar" if it is a class. Something like....
public void Bar<T>(T item)
{
if (typeof(T).IsClass)
this.Foo<T **as class**>();
}
I realise I could use reflection to call Foo, but this just seems like cheating. Is there something I can do with C# to pass "T" on with the constraint at runtime?
Also - I can't change the constraint on the method "Bar" as it comes from an interface so the constraint has to match the constraint on the interface
The only way to call Foo without reflection, is to cast item to one of the types/classes in its hierarchy (after the proper IsClass check).
Obviously, there's only one type in its hierarchy that you know of a priori: Object.
public void Bar<T>(T item)
{
if (typeof(T).IsClass)
this.Foo((object) item);
}
Edit :
Also, in one of the comments you said you added the class constraint to be to instantiate T. You don't need that, what you need is the new constraint.
Unfortunately there is no way to do this without changing Bar to have the generic constraint class or using reflection. In order to compile C# must know at compile time that T is indeed a class value. There is no way to use a dynamic test such as typeof(T).IsClass in order to satisfy this compile time constraint.
You mentioned in the question that you can't change Bar but it seems like you are willing to accept the possibility of dynamic failure. Perhaps instead change Foo to not have the constraint but instead throw an exception when T is not a class type
if (typeof(T).IsClass)
{
this.GetType()
.GetMethod("Foo", System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public)
.Invoke(this, new object[] { item });
}
I believe there is no way to make it compile. You will have to use reflection to make the call.
Actually. You could cheat if you contain it within a class:
public class Container<T>
{
public Container(T value)
{
Value = value;
}
public T Value { get; private set; }
}
public void Bar<T>(T item)
{
this.Foo<Container<T>>(new Container<T>(item));
}
but this adds one layer you need to call-through and makes the types less clear.

How to write a generic method in Java

How to write a generic method in Java.
In C# I would do this
public static T Resolve<T>()
{
return (T) new object();
}
Whats the equivalent in Java?
First, your C# example is wrong; it will throw an InvalidCastException unless typeof(T) == typeof(object). You can fix it by adding a constraint:
public static T Resolve<T>() where T : new() {
return new T();
}
Now, this would be the equivalent syntax in Java (or, at least, as close as we can get):
public static <T> T Resolve() {
return (T) new T();
}
Notice the double mention of T in the declaration: one is the T in <T> which parameterizes the method, and the second is the return type T.
Unfortunately, the above does not work in Java. Because of the way that Java generics are implemented runtime type information about T is not available and so the above gives a compile-time error. Now, you can work around this constraint like so:
public static <T> T Resolve(Class<T> c) {
return c.newInstance();
}
Note the need to pass in T.class. This is known as a runtime type token. It is the idiomatic way of handling this situation.
As other commenters have pointed out, you can do this with Java as well - with as much of a possibility to create a casting exception at runtime:
#SuppressWarnings("unchecked")
public static <T> T resolve() {
return (T) new Object();
}
Unless you use the #SuppressWarnings annotation, however, Java's type erasure comes into play and you will get a compiler warning. The exception will also occur somewhere else: whereever you are trying to use it:
String s = <String>resolve();
will throw the exception.
On the other hand, you probably wanted to use new T() in C# anyway. This you cannot do in Java. The suggested workaround is to use Class<T> as a type parameter if you need to rely on type information at runtime. For your example, this would mean that you have to refactor it to this version:
public static <T> T resolve(Class<T> type) {
try {
return type.newInstance();
} catch(Exception e) {
// deal with the exceptions that can happen if
// the type doesn't have a public default constructor
// (something you could write as where T : new() in C#)
}
}
By the way, you can use this also to get rid of the warning in the previous case and to place the runtime exception at a more sensible line:
public static <T> T resolve(Class<T> type) {
return type.cast(new Object());
}
This piece of code will behave exactly like the one you gave as an example - including an exception that occurs when T is any type different from Object.
Try this http://java.sun.com/docs/books/tutorial/extra/generics/methods.html
public static <T> T Resolve()
{
return (T) new Object();
}
Be careful about (T) but I am not sure that this is correct. I know that generic cast causes a lot of problems. I have already spent with it a lot of time...
You want some kind of factory:
public interface MyFactory<T> {
T newInstance();
}
Then that can be passed into where it is needed. In your code:
public static T resolve<T>(MyFactory<T> factory) {
return factory.newInstance();
}
Note: There is absolutely no reason to be using reflection for this!!

Categories

Resources