Unfortunately there is no possibility of declaring UDF in CLR, with signature you would like (params SqlString[] p). UDF can only have strong type defined list of params, and keyword "params" is not supported currently (I hope this will change in the future also).
Here is the example of String.Format UDF.
[SqlFunction(DataAccess = DataAccessKind.None)]
public static SqlString clr_StringFormat2(SqlString format, object s1, object s2)
{
return format.IsNull ? SqlString.Null : new SqlString(string.Format(format.Value, SqlTypeToNetType(s1, s2)));
}
If you wish more params you will need to add another UDF.
[SqlFunction(DataAccess = DataAccessKind.None)]
public static SqlString clr_StringFormat3(SqlString format, object s1, object s2, object s3)
{
return format.IsNull ? SqlString.Null : new SqlString(string.Format(format.Value, SqlTypeToNetType(s1, s2, s3)));
}
Another thing to keep in mind in .CLR is there is no overloading of methods, so your UDF needs to have unique name.
At the end your UDF it's not possible to implement in .CLR if you have/want unlimited number of parameters. It can be only fixed number of parameters, eg. 4 (as in the case you mentioned).
Reason why to use CLR over SP in such cases is much better performance. But I would also point out that this doesn't mean you will get better performance with .CLR for every possible thing. In some cases T-SQL/PS will perform much better.
Of course everything here depends on assumption that you can deploy .CLR in production environment at the end. If I can deploy .CLR to production and need math, string manipulation or similar things I always use CLR.