Reputation: 32192
I have a simple case where I want to use pattern matching to identify the algorithm I need to use to perform a collision test between two generic Octrees. My basic case is two Octrees of triangles. The skeleton of the code is.
public class Triangle {
public static bool
Intersects
( IReadOnlyList<Triangle> ta
, IReadOnlyList<Triangle> tb)
{
...
}
}
public class Octree<T> {
public bool Intersects<U>(Octree<U> other)
{
if (this is Octree<Triangle> ota && other is Octree<Triangle> otb)
{
return ota.Intersects( otb, Triangle.Intersects );
}
throw new NotImplementedException();
}
public bool Intersects<U>
( Octree<U> other
, Func<IReadOnlyList<T>, IReadOnlyList<U>, bool> intersectsLeaves
)
{
...
}
}
but results in the below error.
Error CS8121
An expression of type Octree<T> cannot be handled by a pattern of type
Octree<Triangle>.
Of course I can just use typeof(U)
and typeof(T)
to do the tests but I thought the above should really work. Why doesn't it?
Upvotes: 1
Views: 1132
Reputation: 32192
There is a work around to the bug/feature. You can use the Try* pattern with inline declared outvariables.
bool TryIs<TU>(object t, out TU u)
{
if (t is TU uu)
{
u = uu;
return true;
}
u = default(TU);
return false;
}
then you can use it like
public bool Intersects<U>(Octree<U> other)
{
if ( TryIs<Octree<Triangle>>(out var ota) && TryIs<Octree<Triangle>>(out var otb))
{
return ota.Intersects( otb, Triangle.Intersects );
}
throw new NotImplementedException();
}
Upvotes: 1
Reputation: 750
Pattern matching in C# 7.0 has a requirement stating that there must be an explicit or implicit conversion from the left-hand-side type to the right-hand-side type.
In C# 7.1, the spec will be expanded so that either the left-hand-side or the right-hand-side can be an open type.
Upvotes: 3
Reputation: 15221
its a bug. take a look at this: https://github.com/dotnet/roslyn/issues/16195
Upvotes: 1