2014-12-03 3 views
2

Я конвертирую кучу строк в api в классы. Я использую экстенсивно компилятор, чтобы помочь мне в этом, так как я могу заменить некоторые типы в core apis и следовать за ошибками типа.Forbid string & object concatenation

Однако, есть разочарование источником ошибок при таком подходе:

// linqpad snippet 
void Main() 
{ 
    var t = "yay : " + (new Foo()); 
    t.Dump(); // "yay: namespace.Foo" instead of compilation error 
} 

class Foo { 
} 

C# будет счастливо сложить строку и любой определенный пользователем объект. Есть ли способ превратить это в предупреждение или ошибку компиляции?

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

+0

Нет предупреждения для написания глупого кода! :) – DavidG

+0

Зачем это должно быть предупреждение или ошибка? – Dennis

+0

@DavidG Я занимаюсь рефакторингом. У меня есть 50+ классов, сообщающихся вместе. Я хочу заменить некоторые данные, представленные строкой, на некоторые другие данные, представленные классом. В классах, использующих конкатенацию строк, я хочу использовать другую форму комбинации. Если компилятор мне не помогает, это означает, что я могу что-то пропустить, и пользователи будут видеть в приложении неактуальные имена классов. – Simon

ответ

3

C# будет счастливо добавлять строку и любой пользовательский объект. Есть ли способ превратить это в предупреждение или ошибку компиляции?

Да - если вы используете Visual Studio 2015 или выше :)

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

Будьте осторожны, как далеко вы продвигаетесь с этим - я обычно стараюсь обрабатывать это в обзоре кода, а не делать его прямой ошибкой. Создание собственного диалекта C# может быть скользким уклоном ...

Обратите внимание, что в некоторых случаях код, который вы указали, может быть полностью уместным - если Foo переопределяет ToString(), например. Вы действительно уверены вы хотите запретить это?

+0

Благодарим вас за ответ. Я уверен, что я хочу запретить это для всех классов, наследующих некоторый абстрактный класс или реализующий данный интерфейс. Я надеялся что-то более простое.Поскольку мы используем visual 2013, я попытаюсь написать правило fxcop. Я надеялся, что существует более простое решение :-(. Такое поведение по умолчанию вместо интерфейса IRepresentable кажется сумасшедшим. – Simon

+0

Мы проводим обзоры, но «поверхность риска» на самом деле очень большая. – Simon

1

Одним из возможных решений (что может быть неуместно) было бы переопределить метод ToString в ваших классах и заставить их выбросить ошибку. Это не даст вам ошибки компиляции времени, но дало бы исключение времени выполнения:

public class Test 
{ 
    public override string ToString() 
    { 
     throw new NotImplementedException(); 
    } 
} 

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

[Obsolete("Don't use this!")] 
public override string ToString() 
{ 
    throw new NotImplementedException(); 
} 

Хотя это не будет иметь никакого влияния на код, который вы в курсе, вы должны получить предупреждения в любом месте вы явно вызвать ToString, для Например, это даст предупреждение компилятору:

var s = (new Test()).ToString(); 
+0

грустно это метод не генерирует предупреждение о 'var s =" "+ (new Test());' – Simon

+0

Да, я упомянул об этом в своем ответе, но он будет генерировать исключения во время выполнения. – DavidG