C # как передать var как параметр функции [duplicate]

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

blockquote>

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

Но если вы не хотите этого делать, вы можете просто сделать переменные общедоступными или защищенными в GlobalState и получить к ним доступ напрямую. И вы можете сделать статический синглтон, поскольку объект приложения JavaDoc указывает :

Как правило, нет необходимости в подклассе Application. В большинстве случаев статические синглтоны могут обеспечивать такую ​​же функциональность более модульным способом. Если вашему singleton нужен глобальный контекст (например, для регистрации широковещательных приемников), функции для его получения можно получить контекст, который внутренне использует Context.getApplicationContext () при первом конструировании singleton.

blockquote>

Использование данных Intent , так как другие ответы здесь - это еще один способ передачи данных, но он обычно используется для небольших данных и простых типов. Вы можете передавать более сложные или более сложные данные, но это более активно, чем просто использование статического одиночного. Объект Application по-прежнему остается моим личным фаворитом для совместного использования более крупных / более сложных несовместимых данных между компонентами Android-приложений (поскольку он имеет четко определенный жизненный цикл в приложении для Android).

Кроме того, как отмечали другие, если данные становятся очень сложными и должны быть постоянными , вы также можете использовать SQLite или файловую систему.

20
задан John Saunders 4 May 2011 в 22:26
поделиться

5 ответов

Вы можете сделать параметр a object:

public void DoSomething(object arg)
{
   //...

Или вы могли бы сделать то, что я предпочитаю, и сделать общий метод:

public void DoSomething<T>(T arg)
{
    //...

Общий подход два основных преимущества, и я приведу примеры того, почему они полезны:

  1. Даже если вы явно не указали тип arg, у вас все еще есть доступ к нему.
  2. Вы можете добавить ограничения на типы, которые хотите разрешить.

Напротив, подход object имеет некоторые важные недостатки:

  1. Поскольку вы рассматриваете arg как object, вы будете только иметь возможность делать то, что вы можете сделать с любым объектом .
  2. Если вы передадите тип значения в качестве параметра object, переменная будет в коробке , что означает удар производительности. Это не огромный удар, но если вы назовете DoSomething несколько тысяч раз подряд, вы можете почувствовать его.

Дженерики и ограничения типов

Добавление type для общего метода позволяет вам ограничить метод, чтобы он принимал только определенные типы. Почему это полезно? Потому что, хотя вы не знаете или не заботитесь о том, с каким конкретным типом вы работаете, вы теперь знаете что-то об этом, и вы можете использовать эту информацию.

Рассмотрим следующую настройку:

public interface IAnimal 
{ 
    void Move(); 
}
public class Duck : IAnimal
{
    public void Move() 
    { 
        Console.WriteLine("Flying"); 
    }
}
public class Fish : IAnimal
{
    public void Move()
    { 
        Console.WriteLine("Swimming"); 
    }
}
public class Ant : IAnimal
{
    public void Move()
    { 
        Console.WriteLine("Walking"); 
    }
}    

Поскольку у нас есть интерфейс IAnimal, мы можем написать общие методы, предназначенные для любой реализации IAnimal:

public class Program
{
    static void DoMove<T>(T animal) where T : IAnimal
    {
        animal.Move();
    }
    public static void Main(string[] args)
    {            
        Duck duck = new Duck(); 
        Fish fish = new Fish();
        Ant ant = new Ant(); 

        DoMove<Duck>(duck);
        DoMove<Fish>(fish);
        DoMove<Ant>(ant);
    }
}

Запустите его: http://rextester.com/GOF1761

Когда мы пишем метод DoMove, нам все равно, будет ли его параметр animal это Duck, a Fish, Ant или что-то еще. Все, о чем мы заботимся, вызывает animal.Move(). Поскольку мы использовали ограничение where T : IAnimal, компилятор знает все, что нам нужно, чтобы знать:

  1. Переменная animal имеет тип T.
  2. Независимо от того, f24], он реализует IAnimal.
  3. Все, что реализует IAnimal, имеет метод Move().
  4. Поэтому мы можем смело называть animal.Move().

(Кстати, да, мы могли бы просто написать DoMove как static void DoMove(IAnimal animal), но это еще одно обсуждение.)

Тип вывода (и некоторые его последствия)

Хорошо, но давайте сделаем еще один шаг. Во многих случаях вы можете вызывать общие методы, не указывая их параметры типа. Это называется выводом типа , и, кроме сохранения некоторого ввода, оно может быть полезно при выполнении той же операции на объектах разных типов.

public static void Main(string[] args)
{            
    IAnimal[] animals = new IAnimal[] 
    {
        new Duck(),
        new Fish(),
        new Ant()
    };

    foreach (IAnimal animal in animals)
    {
        DoMove(animal);
    }
}

Запустить его: http://rextester.com/OVKIA12317

Вам нужно только один раз написать метод DoMove<T>, и вы можете называть его любым типом IAnimal без необходимости давать более конкретный тип. Соответствующая версия Move будет вызываться каждый раз, потому что DoMove<T> может вывести, какой тип использовать для T. Когда вы вызываете DoMove(duck), .NET понимает, что вы действительно имеете в виду DoMove<Duck>(duck), который затем вызывает метод Move в классе Duck.

43
ответ дан Justin Morgan 18 August 2018 в 14:33
поделиться
  • 1
    Я должен упомянуть, что я получил много пользы от такого рода вещей в реальном программировании, и это спасло мне массу времени. Я нашел это особенно полезным в Entity Framework, хотя объяснение моих конкретных случаев использования потребовало бы гораздо больше места. – Justin Morgan 4 May 2011 в 22:40
public void YourMethod<T>(T parameter)
{
}
3
ответ дан Aducci 18 August 2018 в 14:33
поделиться

попытайтесь использовать динамическое ключевое слово, это будет работать, если все ваши разные типы имеют те же методы, которые используются вашими модульными тестами, иначе вы получите исключение во время выполнения

0
ответ дан dmg 18 August 2018 в 14:33
поделиться
4
ответ дан fearofawhackplanet 18 August 2018 в 14:33
поделиться

Вы можете взять object в качестве типа параметра. Еще лучше, возможно, было бы использовать generics:

void MyMethod<T>(T parm) { ... }

Таким образом, этот параметр фактически относится к типу, который прошел пользователь - он не помещается в коробку, как с object и типами значений.

7
ответ дан Kirk Woll 18 August 2018 в 14:33
поделиться
  • 1
    Спасибо, также почему я не могу создать метод с var как входной параметр? Что-то вроде void MyMethod (var par1) {...} – socialMatrix 4 May 2011 в 21:10
  • 2
    @social, разработчики языка C # решили сделать так, чтобы var действителен только для объявлений локальных переменных. В принципе, они могли бы поддерживать его в других конструкциях, таких как параметры метода, но это не добавило бы никакой реальной ценности и сделало бы общедоступные API-интерфейсы класса (методы / свойства / и т. Д.) Менее читабельными. – Kirk Woll 4 May 2011 в 21:17
  • 3
    Имеет смысл. Благодаря :-) – socialMatrix 4 May 2011 в 21:40
  • 4
    @social, на самом деле, подумать об этом, они могли not поддерживать его для параметров метода (ввода), но они могли бы поддерживать его для возвращаемого типа метода (вывода). Это связано с тем, что использование var требует, чтобы переменная была инициализирована декларацией. Очевидно, это было бы невозможно для параметров, так как указанная переменная была бы инициализирована на вызывающем сайте. – Kirk Woll 4 May 2011 в 21:44
Другие вопросы по тегам:

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