#c# #generics #methods #delegates #parameter-passing
Вопрос:
У меня проблема с делегатами и общим типом. Я экспериментирую с делегатами и столкнулся с тем, с чем застрял.
Поэтому я создал функцию, в которой программист может указать функцию сериализации и функцию десериализации. Позже этот класс будет использовать эти функции для сериализации/десериализации данных. Для этого я создал делегат для обоих и метод, который получает делегат сериализации и делегат десериализации.
public static class MyClass
{
public delegate string SerializeAction<T>(T _object);
public delegate T DeserializeAction<T>(string data);
public static SerializeAction serializeAction;
public static DeserializeAction deserializeAction;
public static void SetupConverter<T>(SerializeAction<T> _serializeFunction, DeserializeAction<T> _deserializeFunction)
{
serializeAction = _serializeFunction;
deserializeAction = _deserializeFunction;
}
}
Однако я получаю синтаксическую ошибку при объявлении serializeAction
and deserializeAction
.
Для использования универсального типа ‘SerializeAction’ требуется 1 аргумент типа
Если я использую SerializeAction<T> serializeAction
, то он не может найти T
. И есть еще одна ошибка. Я создал две функции для тестирования SetupConverter
метода.
class DataJSONConverter
{
public static string Serialize<T>(T _object) { return JsonSerializer.Serialize(_object); }
public static T Deserialize<T>(string data) { return JsonSerializer.Deserialize<T>(data); }
}
Это две простые функции, которые используются System.Text.Json
для сериализации. После этого я попытался вызвать метод установки, но снова получил синтаксическую ошибку.
SetupConverter(DataJSONConverter.Serialize, DataJSONConverter.Deserialize);
Появляется следующая ошибка:
Аргументы типа для метода «SetupConverter(SerializeAction, DeserializeAction)» не могут быть выведены из использования. Попробуйте указать аргументы типа явно.
Итак, что я хочу создать в двух словах: у меня есть MyClass
, и у него есть SetupConverter
метод. Передавая две функции в качестве аргументов, программист может указать функции преобразования. Позже, если программист вызовет один из методов MyClass
, который использует преобразование (например, в этом примере), будут использоваться указанные функции.
public static void DoSomething<T>(T _object)
{
string result = serializeAction(_object);
T _object2 = deserializeAction<T>(result);
}
Что я пропустил в делегатах или универсальном типе? Что это за синтаксические ошибки?
Я искренне надеюсь, что кто-нибудь сможет мне в этом помочь, я был бы очень благодарен.
Комментарии:
1.
T
должно быть объявлено на уровне класса, т. е.public static class MyClass<T>
.2. К сожалению, ни один из ответов не решил мою проблему, я все время сталкивался с проблемой «общего поля», о которой упоминал Метельщик . Тем не менее, я многому научился из ответов, так что большое вам спасибо! Я пересмотрел структуру своей программы и заменил «делегатское решение». Если кто-то хочет достичь такой механики, просто скажите мне, и я сделаю все возможное, чтобы объяснить свое решение! Спасибо за вашу помощь!
Ответ №1:
Если у вас есть класс с двумя универсальными методами Method1<T>
и Method2<T>
, то ничто не гарантирует, что на самом T
деле это один и тот же тип. Звонящий принимает решение.
Если вам нужен универсальный класс, который работает только с одним типом, ваш класс должен быть универсальным, а не вашими методами.
public static class MyClass<T>
{
public static Func<T, string> serializeAction;
public static Func<string, T> deserializeAction;
public static void SetupConverter(Func<T, string> _serializeFunction, Func<string, T> _deserializeFunction)
{
serializeAction = _serializeFunction;
deserializeAction = _deserializeFunction;
}
}
Вероятно, вам следует использовать Func<T>
тип вместо делегатов.
Ответ №2:
Похоже, вы ищете универсальные поля, но их нет в C#. В качестве обходного пути вы должны сделать MyClass
универсальный. Классы тоже могут быть общими!
// this should be generic
public static class MyClass<T>
{
// these should not be generic
public delegate string SerializeAction(T _object);
public delegate T DeserializeAction(string data);
private static SerializeAction serializeAction;
private static DeserializeAction deserializeAction;
// this should not be generic
public static void SetupConverter(SerializeAction<T> _serializeFunction, DeserializeAction<T> _deserializeFunction)
{
serializeAction = _serializeFunction;
deserializeAction = _deserializeFunction;
}
// this should not be generic
public static void DoSomething(T _object)
{
string result = serializeAction(_object);
T _object2 = deserializeAction<T>(result);
}
}
Так что скорее, чем
MyClass.DoSomething<Foo>(someFoo);
Вы бы сделали:
MyClass<Foo>.DoSomething(someFoo);