Есть ли способ поддерживать «неявность» в методах расширения? [дублировать]C#

Место общения программистов C#
Ответить
Anonymous
 Есть ли способ поддерживать «неявность» в методах расширения? [дублировать]

Сообщение Anonymous »

В приведенном ниже коде можно ли переписать метод getbar () , чтобы не бросить исключение? />

Код: Выделить всё

Got a BarA
Got a BarClass
Другими словами, правильный метод расширения вызывается, когда в первую очередь используется var . Затем код не удается при вызове метода, потому что мы переходим от «неявного» к «абстрактному», потому что аргумент метода не может быть var type.
Я думаю, что это есть чем заняться со статическим анализом, поскольку изменение var на foo.fooclass или foo.fooa приводит к двум различным результатам (успех или исключение).
the Базовый тип var не изменяется.

Код: Выделить всё

using System;

namespace Foo
{
public abstract class FooClass {}

public class FooA:FooClass {}

public class FooB:FooClass {}

}

namespace Bar
{
public abstract class BarClass {}

public class BarA:BarClass {}

public class BarB:BarClass {}

}

namespace AppLogic
{
public static class App
{
public static void Main()
{
var  f = new Foo.FooA();
Bar.BarClass b = f.Parse();
Bar.BarClass b2 = GetBar(f);

}

static Bar.BarClass GetBar(Foo.FooClass f)
{
return f.Parse();
}

}

public static class Extensions
{
public static Bar.BarA Parse(this Foo.FooA foo)
{
Console.WriteLine("Got a BarA");
return new Bar.BarA();
}

public static Bar.BarClass Parse(this Foo.FooClass foo)
{
Console.WriteLine("Got a BarClass");
throw new InvalidOperationException();
}

public static Bar.BarB Parse(this Foo.FooB foo)
{
Console.WriteLine("Got a BarB");
return new Bar.BarB();
}
}
}
< /code>
Редактировать: < /p>
Этот вопрос был закрыт, и следующая ссылка была предоставлена ​​для справки: < /p>
расширение Метод переоценка < /p>
В связанном вопросе и ответах не было дано практического варианта для имитации «виртуальная диспетчерская», которая является предметом этого поста и прецедента. < /P>
Классы Foo/Bar были слегка отрегулированы для ясности. Последствия для производительности находятся в центре внимания ниже. Эта реализация ограничена закрытым набором типов, которые вы управляете.  < /P>
// Example

Foo f = new Foo1();
Bar b = f.ParseDict();

Foo f2 = new Foo1();
Bar b = f.ParseSwitch();

// Minimal implementation

static class Extensions
{
static Dictionary VTable = new Dictionary
{
{typeof(Foo1), ()=> new Bar1() },
{typeof(Foo2), ()=> new Bar2() },
{typeof(Foo3), ()=> new Bar3() },
{typeof(Foo4), ()=> new Bar4() },
{typeof(Foo5), ()=> new Bar5() },
{typeof(Foo6), ()=> new Bar6() },
{typeof(Foo7), ()=> new Bar7() },
{typeof(Foo8), ()=> new Bar8() },
{typeof(Foo9), ()=> new Bar9() },
{typeof(Foo10), ()=> new Bar10() },
};

public static Bar ParseDict(this Foo foo) => VTable[foo.GetType()]();

public static Bar ParseSwitch(this Foo foo) => foo switch
{
Foo1 => new Bar1(),
Foo2 => new Bar2(),
Foo3 => new Bar3(),
Foo4 => new Bar4(),
Foo5 => new Bar5(),
Foo6 => new Bar6(),
Foo7 => new Bar7(),
Foo8 => new Bar8(),
Foo9 => new Bar9(),
Foo10 => new Bar10(),
_=> throw new ArgumentOutOfRangeException()
};

}

abstract class Foo { }
class Foo1:Foo{ }
class Foo2 : Foo { }
class Foo3 : Foo { }

class Foo4 : Foo { }
class Foo5 : Foo { }
class Foo6 : Foo { }
class Foo7 : Foo { }
class Foo8 : Foo { }
class Foo9 : Foo { }
class Foo10 : Foo { }

abstract class Bar { }
class Bar1 : Bar { }
class Bar2 : Bar { }

class Bar3 : Bar { }
class Bar4 : Bar { }
class Bar5 : Bar { }
class Bar6 : Bar { }
class Bar7 : Bar { }
class Bar8 : Bar { }
class Bar9 : Bar { }
class Bar10 : Bar { }
< /code>
Ниже эталонный эталон вызывает метод расширения 100 000 раз. Различные классы Foo (то есть FOO1-FOO9) использовались, чтобы продемонстрировать, что блок Switch 
выполняет поиск O (n), тогда как словарь-это (1) поиск.
Реализация словаря демонстрирует постоянное время O (1) производительность. < /P>



Метод < /th>
mean < /th>
error < /th>
stddev < /th>
Gen0 < /th>
выделено < /th>
< /tr>
< /thead>
< tbody>

bend_dict_foo1 < /td>
806.9 Us < /td>
9,93 США < /td>
9.29 Us < /td>
183.5938 < /td>
2,29 мб < /td>
< /tr>

bend_dict_foo5 < /td>
806.8 Us < /td>
4.72 US < /td>
4.42 Us < /td>
183.5938 < /td>
2,29 мб < /td>
< /tr>

bend_dict_foo9 < /td>
793.4 Us < /td>
5.30 Us < /td> 4.70 us < /td>
183.5938 < /td>
2,29 мб



< P> Реализация Switch демонстрирует линейную производительность O (n). Как видите, корпус переключения быстрее, если количество типов составляет около 5 или менее. >


method < /th>
mean < /th> error < /th>
stddev < /th>
gen0 < /th>
выделено < /th>
< /tr>
< /thead>


bend_switch_foo1 < /td>
252.8 Us < / td>
4.61 Us < /td>
4.08 Us < /td>
183.5938
2,29 МБ


bend_switch_foo5 < /td>
606.5 Us < /td>
5.75 US < /td>
5.38 Us < /td>
183.5938 < /td>
2,29 мб < /td>
< /tr>
bend_switch_foo6 < /td>
1,160.1 us < /td>
16.40 US
15.34 US
183.5938
2,29 мб < /td>
< /tr>

bend_switch_foo7 < / / td>
1 363,6 US < /td>
9.59 Us < /td>
8.97 Us < /td>
183.5938 < /td>
2,29 мб < /td>
< /tr>

bend_switch_foo8 < /td>
1 464,5 US < /td>
28.32 Us < /td>
26,49 US < /td>
183.5938 < /td>
2,29 мб < /td>
< /tr>

bend_switch_foo9 < /td>
1634,9 US < /td>
18.08 US < /td>
16,91 США < /td>
183.5938 < /td>
2,29 мб < /td>




Подробнее здесь: https://stackoverflow.com/questions/794 ... on-methods
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»