Pergunta

Comparar

String.Format("Hello {0}", "World");

com

"Hello {0}".Format("World");

Por que os designers do .Net escolheram um método estático em vez de um método de instância?O que você acha?

Foi útil?

Solução

Na verdade, não sei a resposta, mas suspeito que tenha algo a ver com o aspecto de invocar métodos diretamente em literais de string.

Se bem me lembro (na verdade, não verifiquei isso porque não tenho um IDE antigo em mãos), as versões anteriores do IDE C# tiveram problemas para detectar chamadas de método em literais de string no IntelliSense, e isso tem um grande impacto na capacidade de descoberta da API.Se fosse esse o caso, digitar o seguinte não ajudaria em nada:

"{0}".Format(12);

Se você fosse forçado a digitar

new String("{0}").Format(12);

Ficaria claro que não havia vantagem em tornar o método Format um método de instância em vez de um método estático.

As bibliotecas .NET foram projetadas pelas mesmas pessoas que nos deram o MFC, e a classe String em particular tem uma forte semelhança com a classe CString no MFC.O MFC possui um método Format de instância (que usa códigos de formatação no estilo printf em vez do estilo de chaves do .NET), o que é doloroso porque não existe um literal CString.Então, em uma base de código MFC em que trabalhei, vejo muito disso:

CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);

o que é doloroso.(Não estou dizendo que o código acima seja uma ótima maneira de fazer coisas mesmo no MFC, mas parece ser assim que a maioria dos desenvolvedores do projeto aprenderam como usar CString::Format).Vindo dessa herança, posso imaginar que os designers da API estavam tentando evitar esse tipo de situação novamente.

Outras dicas

Porque o método Format não tem nada a ver com o valor atual de uma string.

Isso é verdade para todos métodos de string porque as strings .NET são imutáveis.

Se não fosse estático, você precisaria de uma string para começar.

Faz:a string de formato.

Acredito que este seja apenas mais um exemplo das muitas falhas de design na plataforma .NET (e não quero dizer isso como uma chama;Ainda acho o framework .NET superior à maioria dos outros frameworks).

Bem, acho que você precisa ser bastante específico sobre isso, mas, como as pessoas estão dizendo, faz mais sentido String.Format ser estático por causa da semântica implícita.Considerar:

"Hello {0}".Format("World"); // this makes it sound like Format *modifies* 
                             // the string, which is not possible as 
                             // strings are immutable.

string[] parts = "Hello World".Split(' ');    // this however sounds right, 
                                             // because it implies that you 
                                             // split an existing string into 
                                             // two *new* strings.

A primeira coisa que fiz quando atualizei para VS2008 e C#3 foi fazer isso

public static string F( this string format, params object[] args )
{
    return String.Format(format, args);
}

Agora posso alterar meu código de

String.Format("Hello {0}", Name);

para

"Hello {0}".F(Name);

que eu preferia na época.Hoje em dia (2014) eu não me incomodo porque é apenas mais um incômodo continuar adicionando isso a cada projeto aleatório que eu crio, ou vincular em alguma biblioteca de utilitários.

E por que os designers do .NET o escolheram?Quem sabe.Parece totalmente subjetivo.Meu dinheiro está em qualquer um

  • Copiando Java
  • O cara que escreveu na época gostou mais subjetivamente.

Não há realmente nenhuma outra razão válida que eu possa encontrar

Acho que é porque Format não aceita uma string em si, mas uma "string de formato".A maioria das strings são iguais a coisas como "Bob Smith" ou "1010 Main St" ou o que quer que seja e não a "Hello {0}", geralmente você só coloca essas strings de formato quando está tentando usar um modelo para criar outro string, como um método de fábrica e, portanto, se presta a um método estático.

Acho que é porque é um método criador (não tenho certeza se existe um nome melhor).Tudo o que ele faz é pegar o que você fornece e retornar um único objeto string.Não opera em um objeto existente.Se não fosse estático, você precisaria de uma string para começar.

Porque o método Format não tem nada a ver com o valor atual de uma string.O valor da string não é usado.Pega uma string e retorna uma.

Talvez os designers do .NET tenham feito isso porque o JAVA fez assim...

Abrace e estenda.:)

Ver: http://discuss.techinterview.org/default.asp?joel.3.349728.40

Strings .NET são imutáveis
Portanto, ter um método de instância não faz absolutamente nenhum sentido.

Por essa lógica, a classe string não deve ter métodos de instância que retornem cópias modificadas do objeto, mas tem bastante (Trim, ToUpper e assim por diante).Além disso, muitos outros objetos na estrutura também fazem isso.

Concordo que se eles fizessem disso um método de instância, Format parece que seria um nome ruim, mas isso não significa que a funcionalidade não deva ser um método de instância.

Por que não isso?É consistente com o resto de a estrutura .NET

"Hello {0}".ToString("Orion");

Os métodos de instância são bons quando você tem um objeto que mantém algum estado;o processo de formatação de uma string não afeta a string em que você está operando (leia-se:não modifica seu estado), ele cria uma nova string.

Com métodos de extensão, agora você pode ter seu bolo e comê-lo (ou seja,você pode usar a última sintaxe se isso ajudar você a dormir melhor à noite).

Acho que em geral parece melhor usar String.Format, mas vejo sentido em querer ter uma função não estática para quando você já tem uma string armazenada em uma variável que deseja "formatar".

Além disso, todas as funções da classe string não atuam na string, mas retornam um novo objeto string, porque as strings são imutáveis.

@Jared:

Métodos estáticos não sobrecarregados e não herdados (como Class.b(a,c)) que tomam uma instância como a primeira variável são semanticamente equivalentes a uma chamada de método (como a.b(c))

Não, eles não são.

(Supondo que ele seja compilado no mesmo CIL, o que deveria.)

Esse é o seu erro.O CIL produzido é diferente.A distinção é que os métodos membros não podem ser invocados em null valores para que o CIL insira uma verificação em relação null valores.Obviamente, isso não é feito na variante estática.

No entanto, String.Format faz não permitir null valores, então os desenvolvedores tiveram que inserir um cheque manualmente.Deste ponto de vista, a variante do método dos membros seria tecnicamente superior.

Isto é para evitar confusão com .ToString() métodos.

Por exemplo:

double test = 1.54d;

//string.Format pattern
string.Format("This is a test: {0:F1}", test );

//ToString pattern
"This is a test: " + test.ToString("F1");

Se Format fosse um método de instância em string, isso poderia causar confusão, pois os padrões são diferentes.

String.Format() é um método utilitário para transformar vários objetos em uma string formatada.

Um método de instância em uma string faz algo com essa string.

Claro, você poderia fazer:

public static string FormatInsert( this string input, params object[] args) {
    return string.Format( input, args );
}

"Hello {0}, I have {1} things.".FormatInsert( "world", 3);

Não sei por que eles fizeram isso, mas isso realmente não importa mais:

public static class StringExtension
{
    public static string FormatWith(this string format, params object[] args)
    {
        return String.Format(format, args);
    }
}

public class SomeClass
{
    public string SomeMethod(string name)
    {
        return "Hello, {0}".FormatWith(name);
    }
}

Isso flui muito mais fácil, IMHO.

Um grande objetivo de design para C# era tornar a transição de C/C++ para ele o mais fácil possível.Usar a sintaxe de ponto em uma string literal ficaria muito estranho para alguém com experiência apenas em C/C++, e formatar strings é algo que um desenvolvedor provavelmente fará no primeiro dia com a linguagem.Então, acredito que eles o tornaram estático para torná-lo mais próximo de um território familiar.

Outra razão para String.Format é a semelhança com a função printf de C.Era para permitir que os desenvolvedores C tivessem mais facilidade na troca de idiomas.

Não vejo nada de errado em ser estático.

A semântica do método estático parece fazer muito mais sentido para mim.Talvez seja porque é primitivo.Onde os primitivos são usados ​​com frequência, você deseja tornar o código do utilitário para trabalhar com eles o mais leve possível.Além disso, acho que a semântica é muito melhor com String.Format sobre "MyString BLAH BLAH {0}".Formato ...

Métodos estáticos não sobrecarregados e não herdados (como Class.b(a,c)) que tomam uma instância como a primeira variável são semanticamente equivalentes a uma chamada de método (como a.b(c)) então a equipe da plataforma fez uma arbitrária, escolha estética.(Supondo que ele seja compilado no mesmo CIL, o que deveria.) A única maneira de saber seria perguntando por quê.

Possivelmente eles fizeram isso para manter as duas cordas próximas uma da outra lexigraficamente, ou seja,

String.Format("Foo {0}", "Bar");

em vez de

"Foo {0}".Format("bar");

Você deseja saber para onde os índices estão mapeados;talvez eles pensassem que a parte ".Format" apenas adiciona ruído no meio.

Curiosamente, o método ToString (pelo menos para números) é o oposto:number.ToString("000") com a string de formato no lado direito.

Ainda não tentei, mas você pode criar um método de extensão para o que quiser.Eu não faria isso, mas acho que funcionaria.

Também eu acho String.Format() mais alinhado com outros métodos estáticos padronizados, como Int32.Parse(), long.TryParse(), etc.

Você nuvem também basta usar um StringBuilder se você quiser um formato não estático.StringBuilder.AppendFormat()

String.Format deve ser um método estático porque as strings são imutáveis. Torná-lo um método de instância implicaria que você poderia usá-lo para "formatar" ou modificar o valor de uma string existente.Isso você não pode fazer, e torná-lo um método de instância que retornasse uma nova string não faria sentido.Portanto, é um método estático.

String.Format pega pelo menos uma String e retorna uma String diferente.Não é necessário modificar a string de formato para retornar outra string, então não faz muito sentido fazer isso (ignorando a formatação dela).Por outro lado, não seria muito difícil fazer String.Format ser uma função de membro, exceto que não acho que o C# permita funções de membro const como o C++.[Por favor, corrija a mim e a esta postagem, se isso acontecer.]

Strings .NET são imutáveis

Portanto, ter um método de instância não faz absolutamente nenhum sentido.

String foo = new String();

foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method. 

string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top