Определите во время выполнения, если приведение разрешено (C #) - PullRequest
1 голос
/ 23 июня 2010

У меня есть класс-оболочка C # с серией методов, принимающих различные типы данных:

public class MyClass
{
    public void ProcessString(string Value) { // implementation }
    public void ProcessInt(int? Value) { // implementation }\
    public void ProcessOther(MyClass Value) { // implementation }
}

Теперь я хочу добавить универсальный метод ProcessObject(), чтобы избежать необходимости явного приведения объекта перед вызовомсоответствующий метод процесса:

public void ProcessObject(object Value)
{
    if (CanCastToString(Value)
    {
        ProcessString((string)Value);
    }
    else if (CanCastToInt(Value))
    {
        ProcessInt((int?)Value);
    }
    // etc...
}

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

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

(SomeType)Value

работать.

Ответы [ 5 ]

4 голосов
/ 23 июня 2010

Существует два основных способа, которыми это обычно делается:

if (Value is SomeType)
{
    // Do something with a cast
}

или

var v = Value as SomeType;
if (v != null)
{
    // Value was successfully cast as SomeType
}

При работе со структурами или внутренними типами установите их в значение null

1 голос
/ 04 августа 2010

Если (в отличие от OP?) Вы не знаете, какой тип используется до времени выполнения, вы можете попытаться использовать некоторые варианты этого:

http://codegoeshere.blogspot.com/2007/05/dynamic-cast-in-c.html

1 голос
/ 23 июня 2010

Почему бы не предоставить свой API обработки напрямую, с перегрузками для различных параметров?

public class MyClass
{
    public void Process(string Value) { // implementation }
    public void Process(int Value) { // implementation }\
    public void Process(MyClass Value) { // implementation }
    public void Process(object Value) { // catch all method. Handle unknown entities, e.g. call ToString() }
}

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

public class MyClass
{
    void DoProcess(string Value) { // implementation }
    void DoProcess(int Value) { // implementation }\
    void DoProcess(MyClass Value) { // implementation }
    void DoProcess(object Value) { 
        // catch all method. Handle unknown entities, e.g. call ToString()
    }
    public void Process<T>(T value) {
       //this method will call the right overload of DoProcess depending on the compile time type of value. If there isn't a match, it goes to DoProcess(object)
       DoProcess(value);
    }
}

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

if (typeof(short).IsAssignableFrom(Value)
    DoProcess((short)Value);
if (typeof(byte).IsAssignableFrom(Value)
    DoProcess((byte)Value);

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

1 голос
/ 23 июня 2010

вам нужен is оператор.CanCastToString(x) -> x is string.

0 голосов
/ 23 июня 2010
    public void QuickTest()
    {
        object stringObj = "string";
        object nullableInt1 = (int?)null;
        object nullableInt2 = (int?)1;
        object decimalObj = 1.5m;

        ProcessObject(stringObj);
        ProcessObject(nullableInt1);
        ProcessObject(nullableInt2);
        ProcessObject(decimalObj);
    }

    public void ProcessObject(object value)
    {
        if (value == null)
        {
            Debug.WriteLine("null");
            return;
        }


        if (value is string)
        {
            Debug.WriteLine((string)value);
            return;
        }

        string stringValue = value.ToString();

        int intTemp;
        if (int.TryParse(stringValue, out intTemp))
        {
            Debug.WriteLine(intTemp);
            return;
        }

        decimal decimalTemp;
        if (decimal.TryParse(stringValue, out decimalTemp))
        {
            Debug.WriteLine(decimalTemp);
            return;
        }
        // etc...
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...