Почему C # не может вывести этот тип? [Дубликат]

Вот простой надежный способ ...

Поместите следующий код в свою активность, и метод tick () будет вызываться каждую секунду в потоке пользовательского интерфейса, пока ваша активность находится в «возобновленном» " государство. Конечно, вы можете изменить метод tick () для того, чтобы делать то, что вы хотите, или вызывать более или менее часто.

@Override
public void onPause() {
    _handler = null;
    super.onPause();
}

private Handler _handler;

@Override
public void onResume() {
    super.onResume();
    _handler = new Handler();
    Runnable r = new Runnable() {
        public void run() {
            if (_handler == _h0) {
                tick();
                _handler.postDelayed(this, 1000);
            }
        }

        private final Handler _h0 = _handler;
    };
    r.run();
}

private void tick() {
    System.out.println("Tick " + System.currentTimeMillis());
}

Для желающих код «_h0 = _handler» необходим для избегайте одновременного запуска двух таймеров, если ваша активность приостановлена ​​и возобновлена ​​в течение периода тика.

142
задан Robert Harvey 14 June 2013 в 18:50
поделиться

5 ответов

Есть ли философская причина, почему конструктор не может поддерживать вывод типа?

No. Когда у вас есть

new Foo(bar)

, мы могли бы идентифицировать все типы, называемые Foo в области видимости, независимо от общей арности, а затем делать разрешение перегрузки на каждом, используя модифицированный алгоритм вывода типа метода. Мы должны были бы создать алгоритм «блеск», который определяет, какой из двух применимых конструкторов в двух типах, имеющих одно и то же имя, но различные общие атрибуты - лучший конструктор. Чтобы поддерживать обратную совместимость, ctor на не-общий тип должен всегда выигрывать.

Есть ли практическая причина, почему конструктор не может поддерживать вывод типа?

Да. Даже если преимущество функции перевешивает свои издержки - что немаловажно - этого недостаточно для реализации функции. Мало того, что эта функция должна быть чистой победой, она должна быть большой чистой победой по сравнению со всеми другими возможными функциями, в которые мы могли бы инвестировать. Это также должно быть лучше, чем тратить время и усилия по исправлению ошибок, работе с производительностью и другим возможным областям, которые мы могли бы приложить к этим усилиям. И в идеале он должен хорошо вписываться в то, что «тема» относится к выпуску.

Кроме того, как вы правильно заметили, вы можете получить преимущества этой функции, не имея собственно самой функции, используя заводской шаблон. Существование простых обходных решений делает менее вероятным, что функция будет реализована.

Эта функция уже давно находится в списке возможных функций.

UPDATE March 2015

Предлагаемая функция сделала ее достаточно близкой к вершине списка для C # 6, чтобы быть задан и спроектирован, но затем был разрезан.

112
ответ дан Eric Lippert 22 August 2018 в 10:27
поделиться
  • 1
    Это все еще немного странно и непоследовательно, ИМО языковые преимущества функций реализуются последовательно. Но это только мое мнение. – Dykam 25 August 2010 в 22:38
  • 2
    @Triynko: О боже, нет, компилятор C # не может сделать всевозможные возможные выводы. Например, class B<T> { public virtual void M<U>() where U : T {} } class D : B<int> { public override void M<U>() {} } ... (new D()).M(); - вы и я можем использовать наш вывод умственного типа, чтобы знать, что darn уверен, что единственным возможным аргументом типа является int, но компилятор C # пропускает этот трюк. Я мог бы перечислять примеры весь день; наш вывод типа довольно слабый по сравнению с F #. – Eric Lippert 16 March 2012 в 23:54
  • 3
    @Triynko: Или short M<T>(out T y){...} ... var x = M(out x); Вы и я можем рассуждать о том, что единственный возможный тип возврата является коротким, и поэтому x должен быть коротким, и, следовательно, T должен быть коротким. Но компилятор C # падает ниже сразу , если существует цикл any в неявно типизированном локальном. – Eric Lippert 16 March 2012 в 23:59
  • 4
    Или void M<T>(T t1, T t2){} ... M(new Giraffe(), new Turtle());. Я могу рассуждать, что автор кода, вероятно, предполагал, что T является Animal, но компилятор C # не рассуждает и «Жираф и черепаха имеют общий базовый тип Animal, поэтому он является лучшим кандидатом для T», , – Eric Lippert 17 March 2012 в 00:03
  • 5
    Языковая согласованность является приоритетом, но она является низким приоритетом по сравнению с более прагматичными проблемами. И я заверяю вас, что у нас есть список буквально дольше, чем ваша рука функций, которые описывают одно предложение; если бы мы в двадцать раз превышали текущий бюджет, мы все равно не хотели бы внедрять все в этом списке! Поверьте, вы не хотели бы использовать язык, на котором была добавлена ​​каждая возможная функция, которую можно было добавить. Мы выбираем, как проводить наши ограниченные усилия чрезвычайно тщательно, чтобы обеспечить максимальную ценность для клиентов. – Eric Lippert 19 November 2012 в 19:01
1
ответ дан Albin Sunnanbo 22 August 2018 в 10:27
поделиться

Хотя это ответ уже много раз, я чувствую, что мне нужно прояснить одно: C # поддерживает вывод типового типа в конструкторах. Проблема заключается в том, что он не поддерживает ни добавления общих параметров к конструкторам, ни вывода типа type общего типа. Желание вывести аргумент общего типа самого типа в основном совпадает с требованием Foo.Bar(0) сделать вывод Foo<int>.Bar(0).

0
ответ дан IllidanS4 22 August 2018 в 10:27
поделиться

Основная причина, по которой вывод типового типа не может работать над конструкторами, как вы хотите, потому что класс «MyType» даже не существует, когда все, что вы объявили, это «MyType & lt; T & gt;». Помните, что законно иметь оба:

public class MyType<T> {
}

и

public class MyType {
}

Оба будут законными. Как бы вы устранили ваш синтаксис, если бы вы действительно объявили оба, и оба они объявили конфликтующий конструктор.

11
ответ дан Kirk Woll 22 August 2018 в 10:27
поделиться
  • 1
    «Как бы вы устранили ваш синтаксис». В этом случае вам нужно будет указать T. – Pedro Henrique 29 September 2017 в 17:05
public class MyType<T> 
{ 
   private readonly T field; 
   public MyType(T value) { field = value; } 
} 

они могут, нет необходимости рассказывать конструктору «что такое T» снова, поскольку вы уже сделали это в объявлении класса.

также ваша фабрика неверна, вы нужно иметь public class MyTypeFactory<T> не только public class MyTypeFactory - если вы не объявите фабрику внутри класса MyType

Редактировать для обновления:

Ну, это 42 длинный, короткий , int или что-то еще?

Предположим, у вас есть следующее

class Base
{
   public virtual void DoStuff() { Console.WriteLine("Base"); }
}

class Foo : Base
{
   public override void DoStuff() { Console.WriteLine("Foo");  }
}

. Тогда вы сделали это

var c = new Foo();

var myType = new MyType(c);

Ожидаете ли вы foo или base? Нам нужно сообщить компилятору, что использовать вместо T

Когда вы действительно хотели использовать тип base

Следовательно,

var myType = new MyType<Base>(c);
17
ответ дан PostMan 22 August 2018 в 10:27
поделиться
  • 1
    Хороший момент, я хотел сказать, почему компилятор не может вывести тип с помощью конструктора, обновляя мой вопрос. фабрика не должна быть общей, хотя – theburningmonk 25 August 2010 в 22:10
  • 2
    См. Мое редактирование, если фабрика создана внутри класса MyType, он знает, что такое T, но если это не так, вам понадобится T – PostMan 25 August 2010 в 22:14
  • 3
    Компилятор не может вывести тип, потому что мне могут быть несколько конструкторов. Чтобы увеличить ваш пример, как компилятор узнает, какой конструктор должен вызывать, когда MyType(double) присутствует? – Steve Guidi 25 August 2010 в 22:14
  • 4
    @PostMan - но в методе Create компилятор может просто заключить, что T is int – theburningmonk 25 August 2010 в 22:17
  • 5
    @PostMan: часть вашего ответа, с которым я не согласен, - это & ​​lt; quote & gt; ваша фабрика неправильна, вам нужно иметь public class MyTypeFactory<T> не только public class MyTypeFactory - если вы не объявите фабрику внутри класса MyType & lt; / quote & gt; ; Собственно, правильная вещь - это MyTypeFactory.Create<T>, как сейчас задан вопрос, а не MyTypeFactory<T>.Create, который вы сказали. Использование MyTypeFactory<T>.Create предотвратит вывод типа, так как общий параметр, появляющийся перед ссылочным оператором-членом ., не может быть выведен, тот, который может быть использован для метода. – Ben Voigt 6 December 2010 в 03:03
Другие вопросы по тегам:

Похожие вопросы: