How do I reorganize a long chain of speculative proxy casting?

I have C # code that processes XML schemas using the Xml.Schema classes from the .NET platform. Various simple type restrictions are abstracted as part of a whole group of classes derived from Xml.Schema.XmlSchemaFacet. If there isn’t something that I missed, the only way to find out which of the obtained facet types is this facet is to speculatively drop it to one of them, catching the resulting InvalidCastOperation in case of failure. Doing this leaves me with a really ugly function like this:

private void NavigateFacet(XmlSchemaFacet facet)
{
    try
    {
        handler.Length((XmlSchemaLengthFacet)facet);
    }
    catch(InvalidCastException)
    {
        try
        {
            handler.MinLength((XmlSchemaMinLengthFacet)facet);
        }
        catch(InvalidCastException)
        {
            try
            {
                handler.MaxLength((XmlSchemaMaxLengthFacet)facet);
            }
            catch(InvalidCastException)
            {
                ...
            }
        }
    }
}

, ; - , .NET, - . - ?

+3
6

, , XmlSchemaFacet:

Dictionary<Type, Action<XmlSchemaFacet>> HandlerMap = 
   new Dictionary<Type, Action<XmlSchemaFacet>>
{
   {typeof(XmlSchemaLengthFacet), handler.Length},
   {typeof(XmlSchemaMinLengthFacet), handler.MinLength},
   {typeof(XmlSchemaMaxLengthFacet), handler.MaxLength}
};

HandlerMap[facet.GetType()](facet);

KeyNotFoundException, facet . , XmlSchemaFacet, , , , .

, ( , ) , , , if .

+7

as. is. , , as .

:

private void NavigateFacet(XmlSchemaFacet facet)
{
  XmlSchemaLengthFacet lengthFacet = facet as XmlSchemaLengthFacet;
  if (lengthFacet != null)
  {
    handler.Length(lengthFacet);
  }
  else
  {
    // Re-try with XmlSchemaMinLengthFacet, etc.
  }
}
+6
private void NavigateFacet(XmlSchemaFacet facet)
{
    if (facet is XmlSchemaLengthFacet)
    {
        handler.Length((XmlSchemaLengthFacet)facet);
    }
    else if (facet is XmlSchemaMinLengthFacet)
    {
        handler.MinLength((XmlSchemaMinLengthFacet)facet);
    }
    else if (facet is XmlSchemaMaxLengthFacet)
    {
        handler.MinLength((XmlSchemaMaxLengthFacet)facet);
    }

    // etc.
}

. , (is vs. as). , :

object c1 = new Class1();
int trials = 10000000;
Class1 tester;
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i < trials; i++)
{
    if (c1 is Class1)
    {
        tester = (Class1)c1;
    }
}
watch.Stop(); 
MessageBox.Show(watch.ElapsedMilliseconds.ToString()); // ~104 ms 
watch.Reset();
watch.Start();
for (int i = 0; i < trials; i++)
{
    tester = c1 as Class1;
    if (tester != null)
    {
        // 
    }
}
watch.Stop(); 
MessageBox.Show(watch.ElapsedMilliseconds.ToString()); // ~86 ms
watch.Reset();
watch.Start();
for (int i = 0; i < trials; i++)
{
    if (c1 is Class1)
    {
        // 
    }
}
watch.Stop();     
MessageBox.Show(watch.ElapsedMilliseconds.ToString()); // ~74 ms
watch.Reset();
watch.Start();
for (int i = 0; i < trials; i++)
{
    //
}
watch.Stop();     
MessageBox.Show(watch.ElapsedMilliseconds.ToString()); // ~50 ms

, as, , is (36 54 , ).

, is, , (24 ), , is , , , , ( , , ).

, 10 , , . is 0,0000054 , as 0.0000036 ( ).

+4

as - , null .

private void NavigateFacet(XmlSchemaFacet facet)
{
    var length = facet as XmlSchemaLengthFacet;
    if (length != null)
    {
        handler.Length(length);
        return;
    }

    var minlength = facet as XmlSchemaMinLengthFacet;
    if (minlength != null)
    {
        handler.MinLength(minlength);
        return;
    }

    var maxlength = facet as XmlSchemaMaxLengthFacet;
    if (maxlength != null)
    {
        handler.MaxLength(maxlength);
        return;
    }
    ...
}

, (aka Double Despatch, , , .

: as .

2. # 4 , dynamic :

public class HandlerDemo 
{
    public void Handle(XmlSchemaLengthFacet facet) { ... }
    public void Handle(XmlSchemaMinLengthFacet facet) { ... }
    public void Handle(XmlSchemaMaxLengthFacet facet) { ... }
    ...
}

private void NavigateFacet(XmlSchemaFacet facet)
{
    dynamic handler = new HandlerDemo();
    handler.Handle(facet);
}

, , , .

Dynamic Language Runtime (DLR) , , ( ), .

+3

- .

if (facet is XmlSchemaLengthFacet)
{
    handler.Length((XmlSchemaLengthFacet)facet); 
} 
else if (facet is XmlSchemaMinLengthFacet)
{
    handler.MinLength((XmlSchemaMinLengthFacet)facet); 
} 
else if (facet is XmlSchemaMaxLengthFacet)
{
    handler.MaxLength((XmlSchemaMaxLengthFacet)facet); 
} 
else
{
    //Handle Error
}
+1
  • "is", ,

  • "" , ,

:

private void NavigateFacet(XmlSchemaFacet facet)
{
  if (facet is XmlSchemaLengthFacet)
  {
        handler.Length(facet as XmlSchemaLengthFacet);
  }
  else if (facet is XmlSchemaMinLengthFacet)
  {
        handler.MinLength(facet as XmlSchemaMinLengthFacet);
  }
  else if (facet is XmlSchemaMaxLengthFacet)
  {
       handler.MaxLength(facet as XmlSchemaMaxLengthFacet);
  }
}
0

Source: https://habr.com/ru/post/1718653/


All Articles