Очевидный способ для кастинга к объекты фактический тип

То, что я делаю, ищет значение для конкретного поля в хеш-таблице. Объект может быть горсткой типов примитивов, кто значение, предназначен, чтобы быть вставленным XML, но это выходит из хеш-таблицы как из объекта. Таким образом, у меня есть проблема необходимости решить, каков тип, выбросил ее и затем использует, который вводит ToString. Было бы хорошо, если бы я не должен был бросать его, но затем это назовет ToString на типе объекта а не методе дубликата на фактическом типе.

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

public string GetColumnValue(string columnName)
        {
            object value = item[columnName];

            if (value == null)
                return string.Empty;

            if (value.GetType() == typeof(string))
            {
                return (string)value;
            }
            else if (value.GetType() == typeof(double))
            {
                return ((double)value).ToString();
            }
            ...
        }
5
задан Dan Revell 16 February 2010 в 17:19
поделиться

5 ответов

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

Если ваши значения времени поступают из другого места, которое способно к такому разрешению, тогда возьмите эти значения за микросекунды. Умножение на 1000 или деление int на 1000 не даст вам лучшего разрешения, это просто изменит масштаб вашего сравнения.

-121--1948992-

Я думаю, что лучшим решением было бы сделать метод A виртуальным, а не иметь B-повторную реализацию, к которой присоединен интерфейс A (это может потребовать больше работы, чем просто переопределение одной функции), что вы можете сделать так (пример должен быть полным, кроме определения загрузочного интерфейса):

#include <glib-object.h>
#include "fooable.h"

typedef struct {GObject parent;} A;
typedef struct {
    GObjectClass parent;
    gint (*foo) (Fooable *self, gdouble quux);
} AClass;

#define TYPE_A           (a_get_type())
#define A_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST((cls), TYPE_A, AClass))
#define A_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_A, AClass))

gint a_foo_real (Fooable *self, gdouble quux) {
    g_print("a_foo_real(%g)\n", quux);
    return 5;
}

gint a_foo (Fooable *self, gdouble quux) {
    return A_GET_CLASS(self)->foo(self, quux);
}

void implement_fooable (FooableIface *iface) {iface->foo = a_foo;}
void a_class_init      (AClass *cls)         {cls->foo = a_foo_real;}
void a_init            (A *self)             {}

G_DEFINE_TYPE_WITH_CODE(A, a, G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE(TYPE_FOOABLE, implement_fooable));

/* derive class B from A  */
typedef struct {A parent;} B;
typedef struct {AClass parent;} BClass;

#define TYPE_B (b_get_type())

gint b_foo_real (Fooable *self, gdouble quux) {
    g_print("b_foo_real(%g)\n", quux);
    return 55;
}

void b_class_init (BClass *cls) {A_CLASS(cls)->foo = b_foo_real;}
void b_init       (B *self)     {}

G_DEFINE_TYPE(B, b, TYPE_A);

int main () {
    g_type_init();
    A *a = g_object_new(TYPE_A, NULL);
    B *b = g_object_new(TYPE_B, NULL);
    fooable_foo(FOOABLE(a), 87.0); // a_foo_real(87.0) and returns 5
    fooable_foo(FOOABLE(b), 32.0); // b_foo_real(32.0) and returns 55
    return 0;
}

Это не менее краткий пример, чем я могу сделать это. При вызове fooable _ foo () функция просматривает свою таблицу vtable для функции, определенной при реализации интерфейса a _ foo () , которая просматривает таблицу vtable класса A, чтобы определить, какую функцию следует фактически вызвать. Определение класса B переопределяет класс A a _ foo _ real () своим собственным. Если для цепочки требуется b _ foo _ real класса B, это достаточно просто (используйте A _ CLASS (b_parent_class) - > foo () , который определен для вас в макросе G_DEFINE_TYPE)

-121--4781092-

Если все, что вы делаете, это вызываете ToString , из-за полиморфного характера C # ToString вызовет правильную реализацию, даже если все, что у вас есть, является ссылкой на Object.

Например:

var d=DateTime.Now;
object od=d;
Console.WriteLine(od.ToString());
Console.WriteLine(d.ToString());   //same as previous line
8
ответ дан 13 December 2019 в 22:07
поделиться

edit

Если кому-то интересно, здесь коды тестов: http://gist.github.com/raw/305787/dc5349d9f6fa37ee5d621b43ec92dade60fe1c8d/ToStringTests.cs

Ниже вы найдете мой исходный ответ. Кто-то указал, что у вас может быть тип, который не имеет ToString (), который вам нравится (потому что он использует Object или что-то более высокое в цепочке). Лучший способ справиться с этим в версии 3.0+ - использовать такой метод расширения:

    public static class ToStringExpander
    {
       public static string MyToString (this Object x)
       {
          return x.ToString();
       }

       public static string MyToString (this mytype x)
       {
          return "This is the to string of mytype!";
       }
    }

Теперь mytype будет работать с GetColumnValue, указанным ниже, если вы измените ToString () на MyToString ()

исходное сообщение

Это сделает то, что ты хочешь.

   public string GetColumnValue(string columnName)
    {
        object value = item[columnName];

        if (value == null)
            return string.Empty;

        return object.ToString();
    }

или, если вы хотите выглядеть олдскульно:

   public string GetColumnValue(string columnName)
    {
        return (item[columnName] == null ? string.Empty : item[columnName].ToString());
    }

конечно, истинно олдскульный будет сделать макрос #define ...

1
ответ дан 13 December 2019 в 22:07
поделиться

В зависимости от вашего списка допустимых типов вы можете рассмотреть возможность использования Convert.ToString и / или интерфейса IConvertable .

Это позволит вам обрабатывать большинство примитивных типов за один раз.

Однако вам все равно придется обрабатывать вашу нулевую проверку.

1
ответ дан 13 December 2019 в 22:07
поделиться

Почему вы не можете просто использовать .ToString () для значения , поскольку .ToString () наследуется от объекта? Будет вызвана функция .ToString () для соответствующего типа, расположенного дальше по цепочке наследования.

0
ответ дан 13 December 2019 в 22:07
поделиться

ToString () - виртуальный метод. Это означает, что любые вызовы этого метода во время выполнения будут выбирать правильную реализацию («наиболее производный тип»). Поскольку все примитивные типы переопределяют ToString () , чтобы делать правильные вещи, нет причин для какого-либо преобразования к любому типу переменной.

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

int x = 10;
object o = x;
x.ToString();
o.ToString();

Оба вызова ToString () будут выполнять один и тот же код (за вычетом распаковки, которая происходит в версии объекта , поскольку int является типом значения) .

0
ответ дан 13 December 2019 в 22:07
поделиться
Другие вопросы по тегам:

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