bradgonesurfing
bradgonesurfing

Reputation: 32192

Should pattern matching in C# 7 work with generics?

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.

enter image description here

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

Answers (3)

bradgonesurfing
bradgonesurfing

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

Yury Glushkov
Yury Glushkov

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

tlt
tlt

Reputation: 15221

its a bug. take a look at this: https://github.com/dotnet/roslyn/issues/16195

Upvotes: 1

Related Questions