ninjaef Ответов: 2

Этот дизайн хорошо в C#


Просто интересно, является ли это "хорошей практикой" или нет. Я хочу создать класс токенов, который может содержать строку или целое число и обрабатывать токены любого типа. Я посмотрел на открытые дженерики, дженерики, рефераты, переопределения и т. д. и выбрал простое решение ниже:-
using System.IO;
using System;

public class Token 
{
    public dynamic Value {get; set;}
}

class Program
{
    static void Main()
    {   
        Token token1;
        Token token2; 
    
        token1 = new Token();
        token2 = new Token();
        
        token1.Value=1;
        token2.Value="hi";
        Console.WriteLine(token1.Value);
        Console.WriteLine(token2.Value);
        token1.Value=token2.Value;
        Console.WriteLine(token1.Value);
        Console.WriteLine(token2.Value);
    }
}


Что я уже пробовал:

?? как и выше - не знаете, что сюда положить ?

F-ES Sitecore

Вероятно, вам лучше пойти по пути дженериков. Редко бывает так, что вы никогда по-настоящему не заботитесь о рассматриваемом типе, и если все, что вы делаете, это печатаете значение в консоль или журнал и т. д., то у вас может быть базовый универсальный класс и классы concerete, которые наследуют этот базовый класс и предоставляют свои собственные реализации ToString

абстрактный класс MyBaseClass< t>
{
public T Value {get; set;}
абстрактная строка ToString();
}

класс IntClass : MyBaseClass< int>
{
public string ToString()
{
значение.Метод toString();
}
}

Это позволяет вам использовать любой тип, и каждый конкретный класс может затем предоставить свою собственную реализацию ToString, поскольку вы можете захотеть, чтобы "T" был классом типа Person со сложными свойствами.

ninjaef

Мне это нравится. Он также согласуется с базовыми / простыми типами (int, int32,...), не уверен, как вы их называете. Спасибо. Но как мне объявить объект MyBaseClass и вызвать его?Ценность для обоих?

ninjaef

хорошо, но как мне объявить объект для получения токена:

Токен MyBaseClass; //не будет компилироваться?
...
...
token = getNextToken () / / может возвращать строку или int

если<<токен является int>, то ... еще &ЛТ;&ЛТ;маркер строки&ГТ;&ГТ; ...

???

F-ES Sitecore

Вам придется работать с конкретным производным конкретным типом или MyBaseClass< int>, например. Или пусть класс, который должен использовать getNextToken, также будет универсальным классом. Нет никакого реального способа обработки полностью типо-агностических данных, вы должны указать тип в какой-то момент, или getNextToken возвращает фиксированный тип, такой как строка или объект, но опять же вызывающий код должен знать, к какому типу привести. Вы должны подумать о проблеме, которую вы на самом деле пытаетесь решить, .net-это скомпилированный язык, поэтому на самом деле у него нет понятия неопределенных типов.

ninjaef

оригинал ...

токен публичного класса
{
public dynamic Value {get; set;} / / компилируется
}
Токен mytoken = GetNextToken () / / работает во время выполнения; токен.Значение может дать (int) или (char) и т. д.

если mytoken.Тип = число тогда &ЛТ;&ЛТ;лечить как int&ГТ;> еще &ЛТ;&ЛТ;лечить как char&ГТ;&ГТ;

/- значит, полиморфизм?

...

как я уже сказал, Все работает так, как требуется, возможно, проще, чем ваше решение, но мне было интересно, является ли мое решение хорошей практикой - очевидно, оно разрешено в C# и компилируется/запускается

??

F-ES Sitecore

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

ninjaef

довольно самоочевидно, как и выше, я пишу парсер, и это включает в себя токенизатор. каждый токен считывается (getnexttoken) , где тип (int, char, string, other) определяется во время выполнения, поскольку определение токена представляет собой текстовый файл с регулярными выражениями, т. е.

Альфа=[a-z|A-Z]
Цифра=[0-9]
ЦЕЛОЕ ЧИСЛО = ЦИФРА+
ИДЕНТИФИКАТОР = АЛЬФА (АЛЬФА | ЦИФРА)+

и т.д.

таким образом, во время выполнения тип токена определяется грамматикой

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

не так хорошо, как вы говорите, в C#, я согласен, но компилятор позволяет вам это делать, а CLR позволяет вам это запускать!

?

F-ES Sitecore

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

ninjaef

интересно, не могли бы вы объяснить / пример, пожалуйста?
EDIT: токены потребляются как символы, в соответствии с грамматикой, описанной выше, а затем преобразуются в int, если они ЦЕЛОЧИСЛЕННЫ (в соответствии с приведенным выше кодом)и т. д.

F-ES Sitecore

https://www.dotnetperls.com/factory

Для вас Фабрика.Get возьмет токен и в зависимости от его типа вернет конкретный конкретный класс для токена.

ninjaef

ах, прекрасно! и лучшее решение, чем мое, поскольку вы используете типобезопасную логику времени компиляции. БОЛЬШОЕ СПАСИБО!

ninjaef

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

F-ES Sitecore

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

ninjaef

вот оно!

терфейс к настоящему времени:

iproperty публичного интерфейса
{
public String Name { get; }
}

public class Property< t>: IProperty
{
публичное свойство(имя строки, значение T)
{
Имя name;
Value = значение;
}

public String Name { get; private set; }
public T Value { get; private set; }

public override String ToString()
{
возвращенная строка.Формат("{0}: {1}", Имя, Значение)
}
}

...


var intProp = новое свойство< int> ("Возраст", 32);
var strProp = new Property & lt;string> ("name", " Earl");
var enumProp = новое свойство<colorenum & gt; ("цвет глаз", ColorEnum.Пурпурный);


но я действительно не понимаю, что происходит, несмотря на то, что читаю msdn и онлайн

F-ES Sitecore

Когда вы определяете класс;

var intProp = новое свойство<int>();

тогда все, что вы помещаете в угловые браксеты (int в приведенном выше примере), - это то, чем становится "T", так что ваши свойства интерфейса действительно

public String Name { get; private set; }
public int Value { get; private set; }

таким образом, intProp.Value-это int, но strProp.Value-это строка, и вы решаете, каким типом станет "T", когда вы объявите\создадите класс. Однако следует отметить, что элемент "var" не должен вводить вас в заблуждение. var - это не общая переменная, которая может содержать что угодно, это просто "макрос", где var заменяется соответствующим типом вашим компилятором, так что ваш код действительно

Собственность и Л;int&ГТ; intProp = новое свойство И Л;int&ГТ;();
Собственность на<строка> У strProp = новостройку на<строка&ГТ;();

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

2 Ответов

Рейтинг:
2

OriginalGriff

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

public class TokenNumber: Token ...
public class TokenUserName: Token ...
Затем я бы добавил абстрактные методы обработки, которые должен реализовать каждый производный класс. Вполне возможно, что это может быть интерфейс, а не абстрактный класс, но это будет зависеть от того, что еще вам нужно сделать с вашими токенами.
Использование динамической переменной в том виде, в каком вы есть, в основном то же самое, что использование объекта:
public class Token 
{
    public object Value {get; set;}
}
Что побеждает сильную типизацию, которая является одной из причин того, что C# намного лучше VB.


Рейтинг:
2

ninjaef

Используя ваше решение, значение read/write to/from потребует приведения

...
объект значение {получить; набор;}
...
(int)значение
(строковое значение

??