Java.lang.stackoverflowerror вызывает проблемы в моем приложении

Сигнатуры методов

Методы объявляются с помощью ограничений , или , для которых указываются следующие данные.

  • Уровень доступа (необязательно), например или . Значение по умолчанию — .
  • Необязательные модификаторы, например или .
  • Возвращаемое значение или , если у метода его нет.
  • Имя метода.
  • Любые параметры методов. Параметры метода заключаются в скобки и разделяются запятыми. Пустые скобки указывают, что параметры методу не требуются.

Вместе все эти части формируют сигнатуру метода.

Важно!

Тип возврата метода не является частью сигнатуры метода в целях перегрузки метода. Однако он является частью сигнатуры метода при определении совместимости между делегатом и методом, который он указывает.

В следующем примере определяется класс с именем , содержащий пять методов:

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

Объявления об исключениях

Если внутри метода возникает ошибка, метод может вызвать исключение. Исключения должны быть объявлены в объявлении метода следующим образом(выделено жирным шрифтом):

public String concat(String string1, String string2) throws MyException {

    if(string1 == null) {
        throw new MyException("string1 was null");
    }
    if(string2 == null) {
        throw new MyException("string2 was null");
    }

    return string1 + string2;
}

Этот метод сначала проверяет, является ли один из двух параметров string1 или string2 нулевым. Если они есть, исключение выдается. Когда генерируется исключение, метод также прекращает выполнение. Но вместо возврата туда, откуда был вызван, выполнение возобновляется внутри первого предложения catch() {}, окружающего метод, нацеленного на это исключение.

Что такое статические методы в Java?

Статические методы – это методы в Java, которые можно вызывать без создания объекта класса. Они задокументированы именем {class the category}. Статическое ключевое слово может использоваться с классом, переменной, методом и блоком. Статические члены принадлежат классу, а не конкретному экземпляру, это означает, что если вы сделаете член статическим, вы сможете получить к нему доступ без объекта. Давайте рассмотрим пример, чтобы понять это:

Здесь у нас есть статический метод myMethod(), мы можем вызвать этот метод без какого-либо объекта, потому что когда мы делаем член статическим, он становится уровнем класса. Если мы удалим ключевое слово static и сделаем его нестатичным, нам нужно будет создать объект класса для его вызова.

Статические члены являются общими для всех экземпляров (объектов) класса, но нестатические члены являются отдельными для каждого экземпляра класса.

class SimpleStaticExample
{
    // This is a static method
    static void myMethod()
    {
        System.out.println("myMethod");
    }
 
    public static void main(String[] args)
    {
          /* You can see that we are calling this
           * method without creating any object. 
           */
           myMethod();
    }
}

Синтаксис

public static void geek(String name)
{
// code to be executed....

Он хранится в Permanent Generation, поскольку связывается с {class the category}, где они находятся, а не с объектами этого класса. Тем не менее, их локальные переменные, а также передаваемый им аргумент(ы) находятся в стеке.

Важные моменты:

  • Статический метод(ы), связанный с классом, в котором они находятся, то есть они будут ссылаться на него, даже если он не создает экземпляр класса, т.е. ClassName.methodName (args).
  • Они предназначены для совместного использования всеми объектами, созданными из одного класса.
  • Статические методы не могут быть переопределены.

Пример использования статических методов в Java:

import java.io.*;
class Flair{
   public static String FlairName = "";
   public static void geek(String name)
{
         FlairName = name;
   }
}
class GFG {
   public static void main (String[] args) {
         Flair.flair("vaibhav");
         System.out.println(Flair.flairName);
         Flair obj = new Flair ();
         obj.flair("shadow");
         System.out.println(obj.flairName);
   }
}

Вывод:

Что если статическая переменная ссылается на объект?

В первой строке значение, которое будет храниться в разделе PermGen. Во второй строке ссылка obj будет храниться в секции PermGen, а объект, на который она ссылается, будет храниться в секции heap.

Тип возврата метода

Метод может вернуть значение:

public int sum(int value1, int value2) {
    return value1 + value2;
}

Этот метод добавляет два переданных ему параметра и возвращает результат.

Обратите внимание:

  1. На тип возвращаемого значения int, которое выделено жирным шрифтом перед именем метода (сумма). Этот возвращаемый тип сигнализирует, что этот метод возвращает int.
  2. На заявление о возврате. Оператор return определяет, какое значение возвращается методом.

Вы можете вернуть любой примитивный тип или любой объект из метода. Вы также можете вернуть строку, например так:

public String concat(String string1, String string2) {
    return string1 + string2;
}

Этот метод объединяет две строки, переданные в качестве параметров, и возвращает результат.

Рекурсия

Рекурсией называется метод (функция), которая внутри своего тела вызывает сама себя.

Рассмотрим пример — вычисление факториала. Для того чтобы вычислить n!, достаточно знать и перемножить между собой (n-1)! и n.

Создадим метод, реализующий описанный способ.

static int fact (int n) {

  if (n==1) {

    return 1;

  } else if (n==2) {

    return 2;

  } else {

    return fact(n-1) * n;

  }

}

Указанный метод вычисляет факториал натурального числа.

Рассмотрим пример, вычисляющий через рекурсию n-ое число Фибоначчи.

Напомним, как выглядят первые элементы этого ряда: 1 1 2 3 5 8 13 …

static int fib (int n) {

  if (n==1 || n == 2) {

    return 1;

  }

  return fib (n-2) + fib (n-1);

}

Обратите внимание, что в этом методе второй return не помещён в блок else для первого условного оператора. Это допустимо, ведь если выполнится условие и сработает первый return, то произойдёт выход из метода, до второго return исполнение программы дойдёт только в случае невыполнения условия

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

Задачи

  1. Выясните экспериментальном путём, начиная с какого элемента последовательности Фибоначчи, вычисление с использованием рекурсии становится неприемлемым (занимает более минуты по времени).
  2. Создайте гибридный метод, для небольших n вычисляющий n-ое число Фибоначчи с помощью рекурсии, а для значений, превышающих выясненное вами в предыдущей задаче пороговое n, вычисляющий n-ое число Фибоначчи с помощью итерационного алгоритма (цикла, в рамках которого будут сохраняться значения двух предыдущих элементов последовательности).
  3. Подсчитайте, сколько раз потребуется повторно вычислить четвёртый элементы последовательности Фибоначчи для вычисления пятнадцатого элемента.

Стек вызовов

В общем случае в текущий момент времени может исполняться только один единственный метод из всей программы. Это значит, что, если метод а устроен таким образом, что в своём теле он вызывает метод b, а сам а вызывается в main, то при запуске программы управление сначала будет передано методу main, затем методу а, затем методу b. Метод b вернёт результат и управление в а, а вернет результат управления в main, и только потом будут выполняться основные команды, указанные в методе main на остальных строках после вызова a.

Вся иерархия (кто кого вызывал) хранится в специальной области памяти, называемой стеком вызовов. Элементы в этот фрагмент памяти добавляются по следующему принципу: последний добавленный элемент должен быть извлечён первым. Когда работает метод b, получается, что под ним в стеке оказываются метод a и метод main.

В связи с этим в процессе рекурсии существует опасность переполнения стека вызовов.

Существует так называемая сложная рекурсия, при которой метод а вызывает метод b, b вызывает с, а с вызывает а.

Необязательные параметры и аргументы

В определении метода может быть указано, являются его параметры обязательными или нет. По умолчанию параметры обязательны. Для определения необязательных параметров значения параметра по умолчанию включаются в определение метода. Если при вызове метода никакие аргументы для необязательного параметры не указываются, вместо них используется значение по умолчанию.

Значение параметра по умолчанию должно быть назначено одним из следующих видов выражений:

Константа, например, строковый литерал или число.

Выражение, имеющее вид , где может быть либо типом значения, либо ссылочным типом. Использование ссылочного типа практически эквивалентно указанию . Начиная с C# 7.1 вы можете использовать литерал , поскольку компилятор может выводить тип из объявления параметра.

Выражение в форме , где — это тип значения

Обратите внимание на то, что при этом вызывается не имеющий параметров неявный конструктор типа значения, который не является фактическим членом типа.

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

Дополнительные сведения о конструкторах без параметров см. в разделе статьи Типы структур.

Если метод содержит как обязательные, так и необязательные параметры, необязательные параметры определяются в конце списка параметров после всех обязательных параметров.

В следующем примере определяется метод , который имеет один обязательный и два необязательных параметра.

Если для вызова метода с несколькими необязательными аргументами используются позиционные аргументы, вызывающий объект должен предоставить аргумент для всех необязательных параметров, для которых предоставлен аргумент, от первого до последнего. Например, если при использовании метода вызывающий объект предоставляет аргумент для параметра , он должен также предоставить его для параметра . — допустимый вызов метода; вызывает ошибку компилятора «Аргумент отсутствует».

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

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

Использование необязательных параметров влияет на разрешение перегрузки или на способ, с помощью которого компилятор C# определяет, какая именно перегрузка должна вызываться при вызове метода, следующим образом:

  • Метод, индексатор или конструктор является кандидатом на выполнение, если каждый из его параметров необязателен либо по имени или позиции соответствует одному и тому же аргументу в операторе вызова, и этот аргумент можно преобразовать в тип параметра.
  • Если найдено более одного кандидата, правила разрешения перегрузки для предпочтительных преобразований применяются к аргументам, указанным явно. Опущенные аргументы для необязательных параметров игнорируются.
  • Если два кандидата определяются как равно подходящие, предпочтение отдается кандидату без необязательных параметров, аргументы которых в вызове были опущены. Это — последовательность определения приоритетов в разрешении перегрузки для кандидатов с меньшим числом параметров.

Resolving The Problem

Explanations and Solutions

Infinite RecursionJIT/HotSpot Compiled Code

  • JIT Problem Determination for IBM SDK 5.0 and 6.0 using -Xjit
  • Debugging HotSpot failures on the Solaris and HP-UX operating environment

Depleted Native Stack

Detailed Configuration Options

Adjusting the Stack Sizes (Xss and Xmso) options

Maximum Thread Stack Size (-Xss) This parameter controls the stack size of Java method calls (non-native) to track the state of variables. If you find looping code or large stacks that are all calling Java methods and do not make native calls, try raising the stack size by using the generic JVM argument below:

-Xss<size>

Where <size> has the format, nn, such as -Xss512K On Solaris and HP-UX systems which use the HotSpot JVM, there is no distinction between native and thread stack sizes. This is the only configurable value for all stack sizes; however, on HP-UX systems, there is another argument used to control stack size of the main method.

-XX:MainThreadStackSize=<size>

While the -Xss controls the stack size of all threads in native memory, -XX:MainThreadStackSize controls the size of the main thread. The main thread’s native size will be set to whichever value is higher. Initial Thread Stack Size (-Xiss)This is only for distributed platforms (AIX, Linux, Windows) Adjusts the initial thread stack size that the JVM will start with. The default for all distributed platforms is 2KB. In most cases, you will not need to change this option.

-Xiss<size>

Where <size> has the format, nn, such as -Xiss2KInitial Native Stack Size (-Xmso)This is only for distributed platforms (AIX, Linux, Windows) This parameter controls the initial stack size of native (operating system) threads. Java code uses this to process calls made into native libraries, such as JIT or JNI calls. If there is an abundance of calls made on the native stack, adjust the native stack size using this generic JVM argument:

-Xmso<size>

Where <size> has the format, nn, such as -Xmso512K. NOTE: The maximum stack size for the operating system is controlled by ulimit -s on UNIX and Linux.Default Values

Value AIX Linux Windows Solaris HP-UX
Initial Thread Stack Size 2KB 2KB 2KB Not Adjustable Not Adjustable
Maximum Thread Stack Size 256KB (32-bit) 512KB (64-bit) 256KB (32-bit) 512KB (64-bit) 256KB (32-bit) 512KB (64-bit) Not Adjustable Not Adjustable
Native Stack Size 256KB 256KB 32KB (32-bit) 256KB (64-bit) 512KB (32-bit) 1024KB (64-bit) 64KB (PA-RISC) 1024KB (Itanium)

Examples of Stack OverflowServer Logs

SystemOut.log example[3/14/15 3:14:15:926 CST] 31415926 BaseMap       W   CWOBJ0006W: An exception occurred:com.ibm.websphere.objectgrid.ObjectGridRuntimeException: java.lang.StackOverflowError<<Thread stack may follow this message>>SystemErr.log example[3/14/15 3:14:15:926 PST] 31415926 SystemErr     R Caused by: java.lang.StackOverflowError at java.util.Hashtable.get(Hashtable.java:461) at com.ibm.ws.webcontainer.srt.SRTServletRequest.getParameter(SRTServletRequest.java:1257) at psdi.webclient.system.session.WebClientSession.applySkin(WebClientSession.java:295) at psdi.webclient.system.controller.AppInstance.render(AppInstance.java:1177) at psdi.webclient.system.controller.AppInstance.render(AppInstance.java:1213) at psdi.webclient.system.controller.AppInstance.render(AppInstance.java:1213)...Javacore

3XMTHREADINFO      "ORB.thread.pool : 19" (TID:10167F78, sys_thread_t:E072BCE0, state:R, native ID:E06BEBA0) prio=5: pending=java.lang.StackOverflowError

System Dump (processed with jextract and DTFJ Dump Analyzer)

Java stack frames dump is too long: <analyzererror>

Передача по ссылке и передача по значению

При передаче в метод объекта ссылочного типа передается ссылка на этот объект. То есть метод получает не сам объект, а аргумент, который указывает расположение объекта. При изменении члена объекта с помощью этой ссылки это изменение отражается в аргументе в вызывающем методе, даже если объект передается по значению.

Ссылочный тип создается с помощью ключевого слова , как показано в следующем примере.

Теперь, если передать объект, основанный на этом типе, в метод, то будет передана ссылка на объект. В следующем примере объект типа передается в метод :

В этом примере, в сущности, делается то же, что и в предыдущем примере, — аргумент по значению передается в метод. Но поскольку здесь используется ссылочный тип, результат будет другим. В данном случае в методе изменено поле параметра , а также изменено поле аргумента, в методе . В качестве выходных данных метод отображает 33.

Метод экземпляра или статический метод в Java?

  • Метод экземпляра получит прямой доступ к методам экземпляра и переменным.
  • Метод экземпляра будет обращаться к статическим переменным и статическим методам напрямую.
  • Статические методы будут обращаться к статическим переменным и методам напрямую.
  • Статические методы не могут напрямую обращаться к методам экземпляра и переменным экземпляра. И статический метод не может использовать это, так как нет экземпляра для «this», на который можно сослаться.

Оцени статью

Оценить

Средняя оценка / 5. Количество голосов:

Видим, что вы не нашли ответ на свой вопрос.

Помогите улучшить статью.

Спасибо за ваши отзыв!

Методы расширения

Как правило, добавлять методы в существующий тип можно двумя способами:

  • Изменение исходного кода для этого типа. Конечно, если вы не владеете исходным кодом этого типа, сделать это невозможно. Если при этом в поддержку метода также добавляются поля закрытых данных, это изменение становится критическим.
  • Определение нового метода в производном классе. Нельзя добавить метод этим способом, используя наследование для других типов, таких как структуры и перечисления. Кроме того, оно не позволяет «добавить» метод в запечатанный класс.

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

Дополнительные сведения см. в статье Методы расширения.

1 ответ

1

Лучший ответ

Общей причиной является большое количество рекурсивных вызовов — либо из-за ошибки, вызывающей бесконечную рекурсию, либо кода, который только что структурирован, чтобы иметь очень глубокую рекурсию.

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

вы могли бы просто сделать следующее:

06 июнь 2012, в 00:45
Поделиться

Ещё вопросы

  • 1Android: ConcurrentModificationException с наложениями карты
  • Как скрыть значение идентификатора в URL или параметре.
  • Spring: ссылка на ресурсы / статическую папку
  • Приведение из базового класса в шаблон созданного класса
  • RDLC проблема с множественными наборами данных проекта Winform в C #
  • Почему карты объектов C ++ отличаются на Mavericks и Mountain Lion
  • Расположение, верхняя и боковая панели
  • 1Не удалось создать новый проект мобильного модуля Titanium в Titanium 1.8.0.1
  • 1Использование методов внутри циклов, Java и Android
  • 1Как установить / импортировать зависимости и выполнить файл Python в Bluemix
  • Почему моя программа не падает, если деструктор вызывается дважды
  • Изменение размера шрифта с помощью jquery и css
  • 1Как настроить eclipse для запуска только одного исполняемого файла за раз?
  • 1Почему два метода с одинаковым именем невозможны в интерфейсе Android AIDL
  • 1Назначение любого списка в списке на строковый скрипт.
  • Как гарантировать, что API вернется до того, как его обратный вызов будет вызван в асинхронном API (c ++)
  • 1Pandas HDFStore выбрать из вложенных столбцов
  • 1Создание класса javascript без вызова конструктора
  • Я хотел бы изменить #featured ul.ui-tabs-nav при наведении курсора на # nav-фрагмент-1
  • Ионная загрузка в контейнер Certan
  • 2Как я могу включить одно выражение в другое выражение?
  • Если у вас есть функция интерфейса класса, которая вызывает другие внутренние функции?
  • Импорт функции C ++ в тераданные
  • 1Запись в текстовое поле easygui как функция запущена?
  • 1Как расширить панель действий и просмотр списка в одном действии?
  • 2PostAsJsonAsync не вызывает службу webapi из службы windows, используя анонимный тип, что-то очевидно не так?
  • Как заставить circleCI работать с транспортиром baseurl
  • MySQL гарантирует, что каждая строка уникальна
  • Как я могу узнать, происходит ли событие по тому же событию, которое его создало?
  • Объявление функции C ++ и шаблона класса
  • 2Как запустить безопасную службу состояний с отслеживанием состояния в Azure?
  • 1Проверка, является ли конец строки символом пробела
  • Как выполнить взаимодействие между компонентами HTML5 и C ++ в WINCE 7.0?
  • 1Требуется ли для контекста / области видимости сеанса SQLAlchemy неавтоматическое истечение срока действия объекта / атрибута?
  • принять два раза разные значения для разных переменных из одной функции
  • 1Как я могу получить только некоторые конкретные или выбранные контакты из моего списка контактов?
  • 1Как использовать регулярные выражения для проверки наличия двух символов в строке независимо от их местоположения
  • медиазапросы не отвечают нужному размеру экрана
  • 1Статус заказа по умолчанию показывает «обработка», когда заказ размещен в magento?
  • 1Построение массива параметров поиска
  • Как мне вызвать функцию C ++ из JSP
  • 1Проблема перенаправления HTTP на HTTPS
  • Как передать параметр в функцию, когда я не знаю тип
  • заставлять элементы таблицы заполнять родительскую ширину при использовании блока отображения
  • 1Java ничего не возвращает рекурсии
  • Использование функции с интервалом для изменения класса div?
  • 1Объект определяется анонимной функцией, как он работает?
  • Высота анимации на элементе div с различным количеством дочерних элементов
  • 1HTTPRequest не работает (регистрация пользователя в веб-приложении)
  • Прокрутить сообщение до нижней части фиксированного меню

Конечные параметры

Параметр метода может быть объявлен как final, как переменная. Значение окончательного параметра не может быть изменено. То есть, если параметр является ссылкой на объект, ссылка не может быть изменена, но значения внутри объекта все еще могут быть изменены. Вот пример:

public void writeText(final String text1, final String text2) {
    System.out.print(text1);    // read value of text1 parameter.
    System.out.print(text2);    // read value of text2 parameter.
}

В этом примере метода вы не можете переназначить параметры text1 и text2 на любые другие строки, кроме тех, которые были переданы в качестве параметров при вызове.

Возвращаемые

Допустимо иметь более одного оператора возврата в методе. Тем не менее, они не могут быть выполнены оба. После выполнения оператора return больше не выполняется код в этом методе. Программа просто возвращается к коду, который вызвал его.

Вот пример с несколькими операторами возврата:

public String concat(String string1, String string2, boolean reverseOrder){

    if(reverseOrder) {
        return string2 + string1;
    }
    return string1 + string2;
}

Если параметр reverseOrder имеет значение true, то метод возвращает две строки, переданные как параметры, объединенные в обратном порядке (сначала строка2, затем строка1).

Если параметр reverseOrder имеет значение false, то метод пропускает тело оператора if. Затем он продолжается до второго оператора возврата, который возвращает два параметра, соединенных в обычном порядке (строка1, затем строка2).

Ковариантность и контравариантность делегатов

Последнее обновление: 13.10.2018

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

Ковариантность

Ковариантность позволяет возвращать из метода объект, тип которого является производным от типа, возвращаемого
делегатом.

Допустим, имеется следующая структура классов:

class Person
{
	public string Name { get; set; }
}
class Client : Person { }

В этом случае ковариантность делегата может выглядеть следующим образом:

delegate Person PersonFactory(string name);
static void Main(string[] args)
{
    PersonFactory personDel;
    personDel = BuildClient; // ковариантность
    Person p = personDel("Tom");
    Console.WriteLine(p.Name);  
    Console.Read();
}
private static Client BuildClient(string name)
{
    return new Client {Name = name};
}

То есть здесь делегат возвращает объект Person. Однако благодаря ковариантности данный делегат может указывать на метод,
который возвращает объект производного типа, например, Client.

Контрвариантность

Контрвариантность предполагает возможность передавать в метод объект, тип которого является более универсальным по отношению к типу параметра
делегата. Например, возьмем выше определенные классы Person и Client и используем их в следующем примере:

delegate void ClientInfo(Client client);
static void Main(string[] args)
{
    ClientInfo clientInfo = GetPersonInfo; // контравариантность
    Client client = new Client{Name = "Alice"};
    clientInfo(client);
    Console.Read();
}
private static void GetPersonInfo(Person p)
{
    Console.WriteLine(p.Name);
}

Несмотря на то, что делегат в качестве параметра принимает объект Client, ему можно присвоить метод, принимающий в качестве параметра объект базового типа Person.
Может показаться на первый взгляд, что здесь есть некоторое противоречие, то есть использование более универсального тип вместо более
производного. Однако в реальности в делегат при его вызове мы все равно можем передать только объекты типа Client, а любой объект типа Client является объектом типа Person, который используется в методе.

Ковариантность и контравариантность в обобщенных делегатах

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

Например, возьмем следующую иерархию классов:

class Person
{
	public string Name { get; set; }
	public virtual void Display() => Console.WriteLine($"Person {Name}");
}
class Client : Person
{
	public override void Display() => Console.WriteLine($"Client {Name}");
}

Теперь объявим и используем ковариантный обобщенный делегат:

class Program
{
    delegate T Builder<out T>(string name);
    static void Main(string[] args)
    {
        Builder<Client> clientBuilder = GetClient;
		Builder<Person> personBuilder1 = clientBuilder;     // ковариантность
		Builder<Person> personBuilder2 = GetClient;         // ковариантность

		Person p = personBuilder1("Tom"); // вызов делегата
		p.Display(); // Client: Tom
		
        Console.Read();
    }
    private static Person GetPerson(string name)
    {
        return new Person {Name = name};
    }
    private static Client GetClient(string name)
    {
        return new Client {Name = name};
    }
}

Благодаря использованию out мы можем присвоить делегату типа делегат типа
или ссылку на метод, который возвращает значение Client.

Рассмотрим контравариантный обобщенный делегат:

class Program
{
    delegate void GetInfo<in T>(T item);
    static void Main(string[] args)
    {
        GetInfo<Person> personInfo = PersonInfo;
        GetInfo<Client> clientInfo = personInfo;		// контравариантность
        
		Client client = new Client { Name = "Tom" };
        clientInfo(client); // Client: Tom
		
        Console.Read();
    }
    private static void PersonInfo(Person p) => p.Display();
    private static void ClientInfo(Client cl) => cl.Display();
}

Использование ключевого слова in позволяет присвоить делегат с более универсальным типом (GetInfo<Person>)
делегату с производным типом (GetInfo<Client>).

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

НазадВперед

7 ответов

Вы можете использовать DELEGET FUNC в .NET 3.5 в качестве параметра в вашем методе RunTheMethod. Делегат Func позволяет указывать метод, который принимает ряд параметров определенного типа и возвращает один аргумент определенного типа. Вот пример, который должен работать:

ответ дан 22 November 2019 в 21:49

Если Вы хотите передать Метод как параметр, используйте:

ответ дан 22 November 2019 в 21:49

второй класс является Клиентом, который будет использовать класс памяти. Это имеет Основной метод, который создает экземпляр PersonDB, и это называет это методом Процесса objectвЂs с методом, который определяется в Клиентском классе.

ответ дан 22 November 2019 в 21:49

Вам нужно использовать делегат . В этом случае все ваши методы принимают строку параметр и возврат — это наиболее просто представлено функцией делегатом 1 . Таким образом, ваш код может стать правильным с таким простым изменением, как это:

Делегаты имеют гораздо больше мощности, чем это, по общему признанию. Например, с C # вы можете создать делегат из выражения лямбда , поэтому вы можете вызвать ваш метод таким образом:

, который создаст анонимную функцию, подобную этой:

, а затем пройти этот делегат к метод.

Вы можете использовать делегаты для подписок событий, асинхронного исполнения, обратных вызовов — всевозможных вещей. Он стоит читать на них, особенно если вы хотите использовать LINQ. У меня есть статья , которая является в основном в о различиях между делегатами и событиями, но вы можете все равно найти его полезным.

1 Это только основывается на универсальном типа делегата в рамках; Вы можете легко заявить о своих собственных:

, а затем сделать параметр типа вместо этого.

ответ дан 22 November 2019 в 21:49

Вы должны использовать функцию , который представляет функцию, принимающую строку как аргумент и возврат :

Тогда используйте его:

ответ дан 22 November 2019 в 21:49

Вот пример без параметра:
http://en.charp-online.net/csharp_faq:_how_call_a_method_using_a_name_string

С params:

Вы в основном проходите в массиве объектов вместе с именем метода. Затем вы используете как с помощью метода Invoke.

Объект параметров [] Параметры

-121—1781603-

Если вы хотите, чтобы способность меняться, какой метод вызывается во время выполнения, я бы порекомендовал использовать делегат: http://www.codeproject.com/kb/cs/delegates_step1. ASPX

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

ответ дан 22 November 2019 в 21:49

Вот пример без параметра:
http://en.charp-online.net/csharp_faq:_how_call_a_method_using_a_name_string

С params:

Вы в основном проходите в массиве объектов вместе с именем метода. Затем вы используете как с помощью метода Invoke.

Объект параметров [] Параметры

ответ дан 22 November 2019 в 21:49

Другие вопросы по тегам:

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: