Поиск…


замечания

Кастинг - это не то же самое, что конвертировать . Можно преобразовать строковое значение "-1" в целочисленное значение ( -1 ), но это необходимо сделать с помощью таких методов библиотеки, как Convert.ToInt32() или Int32.Parse() . Это невозможно сделать, используя синтаксис casting напрямую.

Передача объекта базовому типу

Учитывая следующие определения:

public interface IMyInterface1
{
    string GetName();
}

public interface IMyInterface2
{
    string GetName();
}

public class MyClass : IMyInterface1, IMyInterface2
{
    string IMyInterface1.GetName()
    {
        return "IMyInterface1";
    }

    string IMyInterface2.GetName()
    {
        return "IMyInterface2";
    }
}

Приведение объекта к примеру базового типа:

    MyClass obj = new MyClass();

    IMyInterface1 myClass1 = (IMyInterface1)obj;
    IMyInterface2 myClass2 = (IMyInterface2)obj;

    Console.WriteLine("I am : {0}", myClass1.GetName());
    Console.WriteLine("I am : {0}", myClass2.GetName());

    // Outputs :
    // I am : IMyInterface1
    // I am : IMyInterface2

Явное литье

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

object value = -1;
int number = (int) value;
Console.WriteLine(Math.Abs(number));

Если мы попытались передать value непосредственно в Math.Abs() , мы получили бы исключение для компиляции, потому что Math.Abs() не имеет перегрузки, которая принимает object в качестве параметра.

Если value не может быть передано в int , тогда вторая строка в этом примере вызовет InvalidCastException

Безопасное явное литье (оператор `as`)

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

object value = "-1";
int? number = value as int?;
if(number != null)
{
    Console.WriteLine(Math.Abs(number.Value));
}

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

Неявное литье

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

int number = -1;
object value = number;
Console.WriteLine(value);

В этом примере нам не нужно было использовать типичный синтаксис синтаксиса, поскольку компилятор знает, что все int s могут быть переданы object s. На самом деле мы могли бы избежать создания переменных и передать -1 непосредственно в качестве аргумента Console.WriteLine() который ожидает object .

Console.WriteLine(-1);

Проверка совместимости без литья

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

if(value is int)
{
   Console.WriteLine(value + "is an int");
}

Явные числовые преобразования

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

double value = -1.1;
int number = (int) value;

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

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

object value = -1.1;
int number = (int) value; // throws InvalidCastException

Операторы преобразования

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

public class JsExpression
{
    private readonly string expression;
    public JsExpression(string rawExpression)
    {
        this.expression = rawExpression;
    }
    public override string ToString()
    {
        return this.expression;
    }
    public JsExpression IsEqualTo(JsExpression other)
    {
        return new JsExpression("(" + this + " == " + other + ")");
    }
}

Если бы мы хотели создать JsExpression, представляющее сравнение двух значений JavaScript, мы могли бы сделать что-то вроде этого:

JsExpression intExpression = new JsExpression("-1");
JsExpression doubleExpression = new JsExpression("-1.0");
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

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

public static explicit operator JsExpression(int value)
{
    return new JsExpression(value.ToString());
}
public static explicit operator JsExpression(double value)
{
    return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = (JsExpression)(-1);
JsExpression doubleExpression = (JsExpression)(-1.0);
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

Или мы могли бы сменить эти операторы на неявные, чтобы сделать синтаксис намного проще.

public static implicit operator JsExpression(int value)
{
    return new JsExpression(value.ToString());
}
public static implicit operator JsExpression(double value)
{
    return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = -1;
Console.WriteLine(intExpression.IsEqualTo(-1.0)); // (-1 == -1.0)

LINQ Операции литья

Предположим, у вас есть такие типы, как:

interface IThing {  }
class Thing : IThing {  }

LINQ позволяет вам создать проекцию, которая изменяет общий тип времени компиляции IEnumerable<> помощью методов расширения Enumerable.Cast<>() и Enumerable.OfType<>() .

IEnumerable<IThing> things = new IThing[] {new Thing()};
IEnumerable<Thing> things2 = things.Cast<Thing>();
IEnumerable<Thing> things3 = things.OfType<Thing>();

Когда things2 оценивается, метод Cast<>() попытается things2 все значения в things в Thing s. Если он встречает значение, которое невозможно выполнить, будет InvalidCastException .

Когда things3 оцениваются, метод OfType<>() будет делать то же самое, за исключением того, что, если он встречает значение, которое невозможно выполнить, он просто опустит это значение, а не выбросит исключение.

Из-за общего типа этих методов они не могут вызывать Операторы преобразования или выполнять числовые преобразования.

double[] doubles = new[]{1,2,3}.Cast<double>().ToArray(); // Throws InvalidCastException

Вы можете просто выполнить бросок внутри .Select() в качестве обходного пути:

double[] doubles = new[]{1,2,3}.Select(i => (double)i).ToArray();


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow