As per the title, is it possible to declare type-negating constraints in c# 4 ?
one use for this would be an option type.
public class Option<A,B>
where A : !B
where B : !A
{
private readonly A a;
private readonly B b;
private Option(){}
public Option(A a)
{
this.a = a
}
public Option(B b)
{
this.b = b
}
}
runtime checking would of course work but you wouldn't have the benefit of type checking at compile time.
No, but it would be possible to check with an "is" and then handle it appropriately...
As far as I know it is not possible to do that.
What you can do is some runtime checking:
public bool MyGenericMethod<T>()
{
// if (T is IEnumerable) // don't do this
if (typeof(T).GetInterface("IEnumerable") == null)
return false;
// ...
return true;
}
No - there's no such concept either in C# or in the CLR.
I found my self trying to implement the same case mentioned in the comments:
void doIt<T>(IEnumerable<T> what) { }
void doIt<T>(T whats) { }
I excepted the following code to reference the first method:
doIt(new List<T>());
But it actually references the second one.
One solution is to cast the argument like this:
doIt(new List<T>().AsEnumerable<T>());
The cast could be hidden by another overload:
void doIt<T>(List<T> whats) {
doIt(whats.AsEnumerable<T>());
}
As far as I know a Not contraint is not possible. You CAN use base classes and/or Interfaces to constrain a Generic. Faced with a similar problem leading to runtime failures, I implemented an interface on the classes the Generic was to handle:
public interface IOperations
{
}
public static T GenericOperationsFactory<T>(ILogger loggerInstance, ref ExecutionContext executionContext)
where T: IOperations
{
var operationsContext = Factories.OperationsContextFactory(loggerInstance, ref executionContext);
var operations = typeof(T).GetConstructor(new[] { typeof(OperationsContext) }).Invoke(new object[] { operationsContext });
return (T)operations;
}
public abstract class OperationsBase:IOperations
{
protected OperationsContext Context { get; set; }
public OperationsBase(OperationsContext context)
{
Context = context;
}
...
public class ListsOperations : OperationsBase
{
public ListsOperations(OperationsContext context) :
base(context)
{
}
alternatively:
public static T GenericOperationsFactory<T>(ILogger loggerInstance, ref ExecutionContext executionContext)
where T: OperationsBase
{
var operationsContext = Factories.OperationsContextFactory(loggerInstance, ref executionContext);
var operations = typeof(T).GetConstructor(new[] { typeof(OperationsContext) }).Invoke(new object[] { operationsContext });
return (T)operations;
}
public abstract class OperationsBase
{
protected OperationsContext Context { get; set; }
public OperationsBase(OperationsContext context)
{
Context = context;
}
...
public class ListsOperations : OperationsBase
{
public ListsOperations(OperationsContext context) :
base(context)
{
}